A. Becerra
A. Becerra

Reputation: 13

Generic Add method in class composed of multiple lists

I have a class composed of multiple lists and I have generic methods to allow me to do CRUD (and other) operations over those lists.

I'm basically trying to do a variation of DbContext.Set<T> with List.

This is my situation:

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
}

The problem is that my code gives me a list of the desired type, but no the actual list (i.e. the property). So any modifications to that list don't modify the property.

I'd like to be able to do something akin to A.List<T> to get the list of that type (like DbContext can do with DbContext.Set<T>).

Upvotes: 1

Views: 45

Answers (1)

Sweeper
Sweeper

Reputation: 271135

You have made a few mistakes here.

  1. Bs and Cs are fields, not properties, so you should use GetFields.

  2. Bs and Cs are private, so you should use the binding flags NonPublic and Instance

  3. The result you get from Where is an IEnumerable<T>. You should call FirstOrDefault or SingleOrDefault to get a single field info.

  4. After getting the field info, you need to call GetValue to get the field's value.

  5. p.GetType() returns typeof(FieldInfo), not the declared type of the field. You should use FieldType instead.

Here is the fixed version:

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

Or, as thehennyy said in the comments, you should probably look into expression trees, specifically MemberExpressions to do this. Reflection is quite slow.

Upvotes: 2

Related Questions