泛型类需要访问Where子句中的属性

时间:2014-03-17 17:16:00

标签: c# entity-framework generics

我目前有一个从基类BaseRepository继承的存储库,如下所示。当它的类型需要一个仪器时,这很好。但是,我不想在派生类中定义GetByType,而是在BaseRepository中定义。显然,BaseRepository中的非抽象方法不起作用,因为它对TEntity中的内容一无所知。即,它不知道i.Type是什么。我该如何实现呢?

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); 
    }
}

2 个答案:

答案 0 :(得分:2)

您需要为TEntity定义一个提供Type方法的界面。

public interface IEntity 
{
     string Type {get;}
}

然后,您可以将基类泛型参数约束到此,这将允许您的现有代码进行编译(因为编译器将知道任何TEntity将具有Type属性可用。)

abstract public class BaseRepository<TEntity>
     where TEntity: IEntity
{

您还必须确保Instrument(以及您实施的任何其他存储库类型)实现IEntity

public class Instrument : IEntity 
{
    public string Type 
    {
         get { return "Instrument" }
    }
}

答案 1 :(得分:0)

我做了一个小帮手,做了一些可能对你有用的事情。

基本上,您可以使用它从属性名称和值创建谓词。

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();
    }

用法如:array.FirstOrDefault(LinqHelper.MakeFilter<YourType>(itemName,valueToLookFor));