C# 泛型类需要访问Where子句中的属性
我目前有一个从基类BaseRepository继承的存储库,如下所示。当一个仪器需要它的类型时,它工作得很好。但是,我不想在派生类中定义GetByType,而是在BaseRepository中定义。显然,BaseRepository中的非抽象方法不起作用,因为它不知道什么是显式的。也就是说,它不知道I.类型是什么。我如何实现这一点C# 泛型类需要访问Where子句中的属性,c#,entity-framework,generics,C#,Entity Framework,Generics,我目前有一个从基类BaseRepository继承的存储库,如下所示。当一个仪器需要它的类型时,它工作得很好。但是,我不想在派生类中定义GetByType,而是在BaseRepository中定义。显然,BaseRepository中的非抽象方法不起作用,因为它不知道什么是显式的。也就是说,它不知道I.类型是什么。我如何实现这一点 public class InstrumentRepository : BaseRepository<Instrument> { // overr
public class InstrumentRepository : BaseRepository<Instrument>
{
// overrides the ABSTRACT method in the base class
public override IEnumerable<Instrument> GetByType(string type)
{
return db.Instruments.Where(i => i.Type == type);
}
}
abstract public class BaseRepository<TEntity>
{
publicMyDbContext db;
internal DbSet<TEntity> dbSet;
public BaseRepository()
{
db = new MyDbContext();
// create a DBSet from the given TEntity
this.dbSet = db.Set<TEntity>();
}
// what I have now
abstract public IEnumerable<TEntity> GetByType(string type);
// I want something like this instead, and I would get rid
// of the abstract method.
public IEnumerable<TEntity> GetByType(string type)
{
// of course this doesn't compile
return dbSet.Where(i => i.Type == type);
}
}
公共类工具库:BaseRepository
{
//重写基类中的抽象方法
公共重写IEnumerable GetByType(字符串类型)
{
返回db.Instruments.Where(i=>i.Type==Type);
}
}
抽象公共类基存储库
{
publicMyDbContext数据库;
内部数据库集;
公共基本存储库()
{
db=新的MyDbContext();
//从给定的tenty创建一个DBSet
this.dbSet=db.Set();
}
//我现在有什么
抽象公共IEnumerable GetByType(字符串类型);
//我想要这样的东西,我会摆脱它
//抽象方法的应用。
公共IEnumerable GetByType(字符串类型)
{
//当然,这不会编译
返回dbSet.Where(i=>i.Type==Type);
}
}
您需要为提供类型方法的tenty
定义一个接口
public interface IEntity
{
string Type {get;}
}
然后,可以将基类泛型参数约束到该参数,这将允许编译现有代码(因为编译器知道任何TEntity
都将有一个类型
属性可用)
我让一个小助手做了一些类似的事情,可能对你有用 实际上,您可以使用它从属性名和值创建谓词
public static Func<TEntity, bool> MakeFilter<TEntity>(string _propertyName, object _value) where TEntity : class
{
var type = typeof(TEntity);
var property = type.GetProperty(_propertyName);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var constantValue = Expression.Constant(_value);
var equality = Expression.Equal(propertyAccess, constantValue);
return Expression.Lambda<Func<TEntity, bool>>(equality, parameter).Compile();
}
public static Func MakeFilter(string _propertyName,object _value),其中tenty:class
{
变量类型=类型(强度);
var property=type.GetProperty(_propertyName);
var参数=表达式参数(类型为“p”);
var propertyAccess=Expression.MakeMemberAccess(参数,属性);
var constantValue=表达式常数(_值);
变量相等=表达式.Equal(propertyAccess,constantValue);
返回表达式.Lambda(相等,参数).Compile();
}
用法如下:
array.FirstOrDefault(LinqHelper.MakeFilter(itemName,valueToLookFor))代码>您不能将“Type”属性放入基类中吗?假设其他子类使用它,.OfType()有什么问题?此扩展方法是在IEnumerable
和IQueryable
或Object#GetType()
和比较类型而不是字符串上定义的。@KrisVandermottenType
是相关对象的一个属性,它实际上不是基于C类型进行过滤的。就是这样。作为补充说明,我还必须添加一个类约束,因为DbSet需要引用类型。谢谢
public class Instrument : IEntity
{
public string Type
{
get { return "Instrument" }
}
}
public static Func<TEntity, bool> MakeFilter<TEntity>(string _propertyName, object _value) where TEntity : class
{
var type = typeof(TEntity);
var property = type.GetProperty(_propertyName);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var constantValue = Expression.Constant(_value);
var equality = Expression.Equal(propertyAccess, constantValue);
return Expression.Lambda<Func<TEntity, bool>>(equality, parameter).Compile();
}