LINQ to Entities - 动态生成谓词的位置

时间:2013-06-07 08:13:21

标签: c# linq-to-entities linq-expressions

我有这个:

public void AssertReadWorks<T>(
    IRepository<T> repository, 
    T entity, 
    Expression<Func<T, T, bool>> keyComparer) where T : class
{
    entity = repository.GetAll().Single(x => x.Id == entity.Id);
}

[TestMethod]
public void ReadTest_DataFieldGroup()
{
    AssertReadWorks(
            _unitOfWork.DataFieldSetRepository, 
            new DataFieldSet { Label = "test", Title = "test" }, 
            (a, b) => a.Id == b.Id);
}

由于不知道T具有Id属性,因此无法编译。请注意,目前尚未使用keyComparer参数。我想使用keyComparer参数(或其他适当的参数)动态生成Single()的谓词:

Expression<Func<T, bool>> keyComparingPredicate = 
    x => a predicate that compares the key of x with the key of `entity`;
entity = repository.GetAll().Single(keyComparingPredicate);

关键是不是所有的Ts都有Id属性,有些会有不同的名字,有些会有复合键。原始AssertReadWorks()如果不是通用的,则可以正常工作。问题是在通用情况下动态构建谓词。如果可以使用与keyComparer参数不同的东西来完成,那么对我来说很好。

有什么想法吗? :)

2 个答案:

答案 0 :(得分:1)

检查,如果这适合你

public T AssertReadWorks<T>(
    IRepository<T> repository,
    Func<T, bool> keyComparer)
{
    return repository.GetAll().Single(keyComparer);
}

使用

[TestMethod]
public void TestInt()
{
    var repository = new Repository<int>( new[] {1, 2, 3} );
    var intEntity = 3;
    AssertReadWorks(repository, e => e == intEntity);
}

[TestMethod]
public void TestString()
{
    var repository = new Repository<string>(new[] { "a", "b", "c" });
    var stringEntity = "A";
    AssertReadWorks(repository, e => string.Equals(e, stringEntity, StringComparison.OrdinalIgnoreCase));
}

[TestMethod]
public void TestThread()
{
    var threadEntity = new Thread(() => { });
    var repository = new Repository<Thread>(new[] { threadEntity, new Thread(() => { }), new Thread(() => { }) });
    AssertReadWorks(repository, e => e.ManagedThreadId == threadEntity.ManagedThreadId);
}

修改 评论回复:

public void AssertReadWorks<T>(
    IRepository<T> repository,
    ref T entity,
    Func<T, T, bool> keyComparer)
{
    var localEntity = entity;
    entity = repository.GetAll().Single(e => keyComparer(e, localEntity));
}

答案 1 :(得分:0)

如果我错了,请纠正我但这个功能的重点是检查相等性吗?要在一般意义上执行此操作,您可以使用IEquatable Interface。这样,您的对象就知道如何将自己与同一个对象进行比较。这应该会减少代码重用,并有助于避免在多个位置创建相同的表达式。

所以你的课程看起来像这样:

public class DataFieldSet : IEquatable<DataFieldSet>
{
    public int Id { get; set; }

    public bool Equals(DataFieldSet other)
    {
        return other != null && this.Id == other.Id;
    }
}

你的断言功能

public void AssertReadWorks<T>(
    IRepository<T> repository, 
    T entity) where T : IEquatable<T>
{
    entity = repository.GetAll().Single(x => entity.Equals(x);
}