C# 有可能在一个地方推广这段代码吗?
我有以下型号:C# 有可能在一个地方推广这段代码吗?,c#,C#,我有以下型号: public class Customer { public int Id {get; set;} public int GroupId {get; set;} public int Number {get; set;} public string Name {get; set;} } 我的所有域模型都包含GroupId属性。为用户分配了GroupId,当用户创建实体时,其GroupId将与实体一起保存。用户只能对具有其GroupId的实体执行C
public class Customer
{
public int Id {get; set;}
public int GroupId {get; set;}
public int Number {get; set;}
public string Name {get; set;}
}
我的所有域模型都包含GroupId
属性。为用户分配了GroupId
,当用户创建实体时,其GroupId
将与实体一起保存。用户只能对具有其GroupId
的实体执行CRUD操作
因此,目前,在我的服务层,基于PredicateBuilder
扩展,我有一个方法,在加载实体时添加GroupId
:
public Customer Get(Expression<Func<Customer, bool>> where)
{
var addGroup = groupRepository.Get(EntityType.Customer).AddGroup;
if (addGroup)
where = where.And(x => x.GroupId == user.GroupId);
return customerRepository.Get(where);
}
公共客户获取(表达式where)
{
var addGroup=groupRepository.Get(EntityType.Customer).addGroup;
如果(添加组)
其中=where.And(x=>x.GroupId==user.GroupId);
返回customerRepository.Get(在何处);
}
每个Get
方法都执行上述操作
有没有办法将上述代码集中在一个地方,而不必在我所有服务的每个
Get
方法中重复代码?您可以提取接口
public interface IGroup
{
int GroupId {get; set;}
}
然后更新您的方法以使用该接口:
public IGroup Get(Expression<Func<IGroup, bool>> where)
{
var addGroup = groupRepository.Get(EntityType.Customer).AddGroup;
if (addGroup)
where = where.And(x => x.GroupId == user.GroupId);
return customerRepository.Get(where);
}
我的所有域模型都包含GroupId属性
然后,您的所有域模型都应该实现一个定义GroupId
属性的接口(我们称之为IHasGroup
)
然后,分解代码应该很容易:
public Customer Get(Expression<Func<Customer, bool>> where)
{
return GetHelper(EntityType.Customer, where, customerRepository.Get);
}
public static T GetHelper<T>(EntityType type, Expression<Func<T, bool>> where,
Func<Expression<Func<T, bool>>, T> repositoryAccessor)
where T : IHasGroup
{
var addGroup = groupRepository.Get(type).AddGroup;
if (addGroup)
where = where.And(x => x.GroupId == user.GroupId);
return repositoryAccessor(where);
}
公共客户获取(表达式where)
{
返回GetHelper(EntityType.Customer,其中,customerRepository.Get);
}
公共静态T GetHelper(EntityType类型,表达式,其中,
Func repositoryAccessor)
其中T:IHasGroup
{
var addGroup=groupRepository.Get(type).addGroup;
如果(添加组)
其中=where.And(x=>x.GroupId==user.GroupId);
返回存储存取器(其中);
}
将customerRepository封装在用户特定的customerRepository中,如
public class UserSpecificCustomerRepository : ICustomerRepository{
private User _user;
private ICustomerRepository _customerRepository;
public UserSpecificCustomerRepository(User user, ICustomerRepository repo){
_user = user;
_customerRepository = repo;
}
public Customer Get(Expression<Func<Customer, bool>> where){
where = where.And(x => x.GroupId == _user.GroupId);
_customerRepository.Get(where);
}
}
公共类UserSpecificCustomerRepository:ICCustomerRepository{
私人用户(u User),;
专用ICCustomerRepository\u customerRepository;
公共用户特定CustomerRepository(用户用户,ICCustomerRepository repo){
_用户=用户;
_customerRepository=回购;
}
公共客户获取(表达式where){
其中=where.And(x=>x.GroupId==\u user.GroupId);
_customerRepository.Get(在何处);
}
}
现在只有一个地方可以扩展表达式。您的代码将更改为
public Customer Get(Expression<Func<Customer, bool>> where)
{
var addGroup = groupRepository.Get(EntityType.Customer).AddGroup;
if (addGroup) {
return new UserSpecificCustomerRepository(user, customerRepository).Get(where);
}
return customerRepository.Get(where);
}
公共客户获取(表达式where)
{
var addGroup=groupRepository.Get(EntityType.Customer).addGroup;
如果(添加组){
返回新的UserSpecificCustomerRepository(用户,customerRepository).Get(其中);
}
返回customerRepository.Get(在何处);
}
尝试使用baseEntity,并在其基础上使用一些常用方法
然后在所有实体中继承baseEntity,这样每个实体都有通用方法
public class EntityBase<T>
{
public virtual T Get(Expression<Func<T, bool>> where)
{
//your Logic here
}
public virtual IEnumerable<T> GetAll()
{
//Your Logic here
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
//Your Logic here
}
}
公共类EntityBase
{
公共虚拟T Get(表达式,其中)
{
//你的逻辑在这里
}
公共虚拟IEnumerable GetAll()
{
//你的逻辑在这里
}
公共虚拟IEnumerable GetMany(表达式,其中)
{
//你的逻辑在这里
}
}
希望这能对您有所帮助。他们能从基本实体继承吗?@Sayse只有在EF Code First允许TPH的情况下才能在上述情况下使用。恐怕我对Code First或TPH的了解不够,无法知道答案(如果EF Code First允许的话)。。。我的想法是使用泛型基类。。。我遇到以下异常:
无法将类型“Customer”强制转换为类型“IHasGroup”。LINQ to实体仅支持强制转换EDM基元或枚举类型。
Ok解决了它。刚刚添加了类
约束,效果很好。这是一个常见问题。如果使用接口,则无法在Linq查询中使用,因为实体框架不知道此属性。如果您想这样做,您需要让您的所有实体从同一个基本实体继承,这很可能是一个大禁忌。。。
public class EntityBase<T>
{
public virtual T Get(Expression<Func<T, bool>> where)
{
//your Logic here
}
public virtual IEnumerable<T> GetAll()
{
//Your Logic here
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
//Your Logic here
}
}