由多个列表组成的类中的通用Add方法

时间:2018-10-13 15:18:42

标签: c# reflection

我有一个由多个列表组成的类,并且有通用的方法可以让我对这些列表进行CRUD(及其他)操作。

我基本上是在尝试将DbContext.Set<T>改成List

这是我的情况:

public class A
{
    private IList<B> Bs;
    private IList<C> Cs;

    public A()
    {
        Administrators = new List<B>();
        Developers = new List<C>();
    }

    public void Add<T>(T entity)
    {
        var propertyIWant = this.GetType().GetProperties().Where(p => p.GetType() == typeof(IList<T>));
        var propertyAsList = propertyIWant as List<T>;
        propertyAsList.Add(entity);
    }

    public void Delete<T>(T entity)
    {
       //Same idea 
    }

    //Other methods
}

问题是我的代码为我提供了所需类型的列表,但没有 actual 列表(即属性)。 因此,对该列表的任何修改都不会修改该属性。

我希望能够进行类似于A.List<T>的操作来获取该类型的列表(例如DbContext可以与DbContext.Set<T>一起使用)。

1 个答案:

答案 0 :(得分:2)

您在这里犯了一些错误。

  1. BsCs是字段,而不是属性,因此您应使用GetFields

  2. BsCs是私有的,因此应使用绑定标志NonPublicInstance

  3. Where获得的结果是IEnumerable<T>。您应该致电FirstOrDefaultSingleOrDefault以获得单个字段信息。

  4. 获取字段信息后,您需要调用GetValue来获取字段的值。

  5. p.GetType()返回typeof(FieldInfo),而不是字段的声明类型。您应该改用FieldType

这是固定版本:

public void Add<T>(T entity)
{
    var fieldIWant = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(p => p.FieldType == typeof(IList<T>)).SingleOrDefault();
    if (fieldIWant != null) {
        var value = (IList<T>)fieldIWant.GetValue(this);
        value.Add(entity);
    }
}

或者,正如thehennyy在评论中所说,您可能应该查看表达式树,特别是MemberExpression来做到这一点。反射速度很慢。