在Suteki.Shop中Model的原型是基于Linq to SQL创建的,其dbml文件位于Suteki.Shop\Shop.dbml。而Suteki.Shop在此文件的基本上,以"partial class "的方式在Suteki.Shop\Model文件夹下创建了相应的类文件以扩展Shop.dbml中Model类的一些方法和属性声明,如下图:
为了便于大家理解,下面以Model中的Product.cs为例进行说明。
Product是对网站中所销售商品的数据信息类。在其中定义了一些属性(声明在Shop.dbml中):
Product是对网站中所销售商品的数据信息类。在其中定义了一些属性(声明在Shop.dbml中):
private
int
_ProductId;
//
产品ID
private int _CategoryId; // 产品所属分类ID
private string _Name; // 产品名称
private string _Description; // 产品描述
private decimal _Price; // 产品价格
private int _Position; // 在列表中的位置
private int _Weight; // 重量
private bool _IsActive; // 当前是否激活显示
private string _UrlName; // 产品的URL链接
private int _CategoryId; // 产品所属分类ID
private string _Name; // 产品名称
private string _Description; // 产品描述
private decimal _Price; // 产品价格
private int _Position; // 在列表中的位置
private int _Weight; // 重量
private bool _IsActive; // 当前是否激活显示
private string _UrlName; // 产品的URL链接
而Product.cs这个文件其实是以partial方式对Shop.dbml中的Product类的"扩展",下面是其实现代码:
public
partial
class
Product : IOrderable, IActivatable, IUrlNamed
{
partial void OnNameChanging( string value)
{
value.Label( " Name " ).IsRequired();
}
partial void OnNameChanged()
{
UrlName = Name.ToUrlFriendly();
}
partial void OnDescriptionChanging( string value)
{
value.Label( " Description " ).IsRequired();
}
public bool HasMainImage
{
get
{
return this .ProductImages.Count > 0 ;
}
}
public Image MainImage
{
get
{
if (HasMainImage) return this .ProductImages.InOrder().First().Image;
return null ;
}
}
public bool HasSize
{
get
{
return this .Sizes.Active().Count() > 0 ;
}
}
public Size DefaultSize
{
get
{
if ( this .Sizes.Count() == 0 ) throw new ApplicationException( " Product has no default size " );
return this .Sizes[ 0 ];
}
}
public string IsActiveAsString
{
get
{
if (IsActive) return string .Empty;
return " Not Active " ;
}
}
public static Product DefaultProduct( int parentCategory, int position)
{
return new Product
{
ProductId = 0 ,
CategoryId = parentCategory,
Position = position
};
}
}
{
partial void OnNameChanging( string value)
{
value.Label( " Name " ).IsRequired();
}
partial void OnNameChanged()
{
UrlName = Name.ToUrlFriendly();
}
partial void OnDescriptionChanging( string value)
{
value.Label( " Description " ).IsRequired();
}
public bool HasMainImage
{
get
{
return this .ProductImages.Count > 0 ;
}
}
public Image MainImage
{
get
{
if (HasMainImage) return this .ProductImages.InOrder().First().Image;
return null ;
}
}
public bool HasSize
{
get
{
return this .Sizes.Active().Count() > 0 ;
}
}
public Size DefaultSize
{
get
{
if ( this .Sizes.Count() == 0 ) throw new ApplicationException( " Product has no default size " );
return this .Sizes[ 0 ];
}
}
public string IsActiveAsString
{
get
{
if (IsActive) return string .Empty;
return " Not Active " ;
}
}
public static Product DefaultProduct( int parentCategory, int position)
{
return new Product
{
ProductId = 0 ,
CategoryId = parentCategory,
Position = position
};
}
}
首先要说明的是 OnNameChanging方法,该方法的声明如下(位于Shop.dbml中):
partial
void
OnNameChanging(
string
value);
并且在dbml中相应的产品"Name"属性中对其进行调用:
[Column(Storage
=
"
_Name
"
, DbType
=
"
NVarChar(250) NOT NULL
"
, CanBeNull
=
false
)]
public string Name
{
get
{
return this ._Name;
}
set
{
if (( this ._Name != value))
{
this .OnNameChanging(value);
this .SendPropertyChanging();
this ._Name = value;
this .SendPropertyChanged( " Name " );
this .OnNameChanged();
}
}
}
public string Name
{
get
{
return this ._Name;
}
set
{
if (( this ._Name != value))
{
this .OnNameChanging(value);
this .SendPropertyChanging();
this ._Name = value;
this .SendPropertyChanged( " Name " );
this .OnNameChanged();
}
}
}
这样做的目的就是在产品的名称发生变更时调用该方法以进行处理,当然该set中还有一些其它方法的调用,这里要不多做说明了。下面接着看一下partial类中OnNameChanging方法所做的工作:
partial
void
OnNameChanging(
string
value)
{
value.Label( " Name " ).IsRequired();
}
{
value.Label( " Name " ).IsRequired();
}
下面是其相关的接口声明:
public
interface
IRepository
<
T
>
where
T :
class
{
T GetById( int id);
IQueryable < T > GetAll();
void InsertOnSubmit(T entity);
void DeleteOnSubmit(T entity);
[Obsolete( " Units of Work should be managed externally to the Repository. " )]
void SubmitChanges();
}
public interface IRepository
{
object GetById( int id);
IQueryable GetAll();
void InsertOnSubmit( object entity);
void DeleteOnSubmit( object entity);
[Obsolete( " Units of Work should be managed externally to the Repository. " )]
void SubmitChanges();
}
{
T GetById( int id);
IQueryable < T > GetAll();
void InsertOnSubmit(T entity);
void DeleteOnSubmit(T entity);
[Obsolete( " Units of Work should be managed externally to the Repository. " )]
void SubmitChanges();
}
public interface IRepository
{
object GetById( int id);
IQueryable GetAll();
void InsertOnSubmit( object entity);
void DeleteOnSubmit( object entity);
[Obsolete( " Units of Work should be managed externally to the Repository. " )]
void SubmitChanges();
}
做为实现上面两个接口的“Repository”类,其承担了对CRUD的具体操作逻辑实现。
public
class
Repository
<
T
>
: IRepository
<
T
>
, IRepository
where
T :
class
{
readonly DataContext dataContext;
public Repository(IDataContextProvider dataContextProvider)
{
dataContext = dataContextProvider.DataContext;
}
public virtual T GetById( int id)
{
var itemParameter = Expression.Parameter( typeof (T), " item " );
var whereExpression = Expression.Lambda < Func < T, bool >>
(
Expression.Equal(
Expression.Property(
itemParameter,
typeof (T).GetPrimaryKey().Name
),
Expression.Constant(id)
),
new [] { itemParameter }
);
return GetAll().Where(whereExpression).Single();
}
public virtual IQueryable < T > GetAll()
{
return dataContext.GetTable < T > ();
}
public virtual void InsertOnSubmit(T entity)
{
GetTable().InsertOnSubmit(entity);
}
public virtual void DeleteOnSubmit(T entity)
{
GetTable().DeleteOnSubmit(entity);
}
public virtual void SubmitChanges()
{
dataContext.SubmitChanges();
}
public virtual ITable GetTable()
{
return dataContext.GetTable < T > ();
}
IQueryable IRepository.GetAll()
{
return GetAll();
}
void IRepository.InsertOnSubmit( object entity)
{
InsertOnSubmit((T)entity);
}
void IRepository.DeleteOnSubmit( object entity)
{
DeleteOnSubmit((T)entity);
}
object IRepository.GetById( int id)
{
return GetById(id);
}
}
{
readonly DataContext dataContext;
public Repository(IDataContextProvider dataContextProvider)
{
dataContext = dataContextProvider.DataContext;
}
public virtual T GetById( int id)
{
var itemParameter = Expression.Parameter( typeof (T), " item " );
var whereExpression = Expression.Lambda < Func < T, bool >>
(
Expression.Equal(
Expression.Property(
itemParameter,
typeof (T).GetPrimaryKey().Name
),
Expression.Constant(id)
),
new [] { itemParameter }
);
return GetAll().Where(whereExpression).Single();
}
public virtual IQueryable < T > GetAll()
{
return dataContext.GetTable < T > ();
}
public virtual void InsertOnSubmit(T entity)
{
GetTable().InsertOnSubmit(entity);
}
public virtual void DeleteOnSubmit(T entity)
{
GetTable().DeleteOnSubmit(entity);
}
public virtual void SubmitChanges()
{
dataContext.SubmitChanges();
}
public virtual ITable GetTable()
{
return dataContext.GetTable < T > ();
}
IQueryable IRepository.GetAll()
{
return GetAll();
}
void IRepository.InsertOnSubmit( object entity)
{
InsertOnSubmit((T)entity);
}
void IRepository.DeleteOnSubmit( object entity)
{
DeleteOnSubmit((T)entity);
}
object IRepository.GetById( int id)
{
return GetById(id);
}
}
在上面的类图中,还有两个类也很重要,其中IRepositoryResolver是一个分析器接口,其定义了“传入一个type类型并在Castle容器中获取该type组件实例的方法声明”,而作为其接口具体实现,“RepositoryResolver”的实现代码如下:
public
class
RepositoryResolver : IRepositoryResolver
{
private readonly IKernel kernel;
public RepositoryResolver(IKernel kernel)
{
this .kernel = kernel;
}
public IRepository < T > GetRepository < T > () where T : class
{
Type repositoryType = typeof (IRepository <> ).MakeGenericType( new [] { typeof (T) });
var repository = kernel.Resolve(repositoryType) as IRepository < T > ;
if (repository == null )
{
throw new ApplicationException(StringExtensions.With( " Could not find IRepository<{0}> in kernel " , typeof (T).Name));
}
return repository;
}
public IRepository GetRepository(Type type)
{
Type repositoryType = typeof (IRepository <> ).MakeGenericType( new [] { type });
var repository = kernel.Resolve(repositoryType);
if (repository == null )
{
throw new ApplicationException( " Could not find IRepository<{0}> in kernel " .With(type.Name));
}
if ((repository as IRepository) == null )
{
throw new ApplicationException( " The repository that implements IRepository<{0}> does not implement IRepository " .With(type.Name));
}
return (IRepository)repository;
}
}
{
private readonly IKernel kernel;
public RepositoryResolver(IKernel kernel)
{
this .kernel = kernel;
}
public IRepository < T > GetRepository < T > () where T : class
{
Type repositoryType = typeof (IRepository <> ).MakeGenericType( new [] { typeof (T) });
var repository = kernel.Resolve(repositoryType) as IRepository < T > ;
if (repository == null )
{
throw new ApplicationException(StringExtensions.With( " Could not find IRepository<{0}> in kernel " , typeof (T).Name));
}
return repository;
}
public IRepository GetRepository(Type type)
{
Type repositoryType = typeof (IRepository <> ).MakeGenericType( new [] { type });
var repository = kernel.Resolve(repositoryType);
if (repository == null )
{
throw new ApplicationException( " Could not find IRepository<{0}> in kernel " .With(type.Name));
}
if ((repository as IRepository) == null )
{
throw new ApplicationException( " The repository that implements IRepository<{0}> does not implement IRepository " .With(type.Name));
}
return (IRepository)repository;
}
}
上面的部分代码涉及到了castle框架的核心功能,可以参见我写的
}
}
本文转自 daizhenjun 51CTO博客,原文链接:http://blog.51cto.com/daizhj/161776,如需转载请自行联系原作者