FastMember ObjectReader doesn't work with inhe

2019-05-10 06:59发布

问题:

I get an interface as return from a library that I have no control over:

public interface IA : IB { String A { get;} }
public interface IB { String B { get;} }

Now when I try to run this code, I get an exception:

List<IA> list = library.Get();
IDataReader r = ObjectReader.Create(list, nameof(IA.A), nameof(IA.B));
while (r.Read())
{
    for (Int32 i = 0; i < r.FieldCount; i++)
    {
        //HERE ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: name
        Object o = r[i];
        Console.Write(o + ",");
    }
    Console.WriteLine();
}

It seems like it doesn't find the B property because it's declared in IB. I confirmed this by making a test and having B in IA directly.

I have found a very bad workaround, which involves creating a new class that implements IA:

public class Ab : IA
{
    public Ab(String a, String b)
    {A = a;B=b;}

    public String A { get;}
    public String B { get;}
}

and then convert the List<IA> as such: List<Ab> newList = l.Select(e => new Ab(e.A, e.B).ToList(), then ObjectReader.Create(newList). ObjectReader seems to find the B property when I do this. But that seems very wasteful on resources (and a lot of code) to create this intermediary objects with the exact same content.

Any idea if it's possible to solve in another way that doesn't involve creating new objects?

回答1:

I cloned the Repository of the FastMember Package, in the TypeAccessor class I changed line 265 from:

PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

to:

PropertyInfo[] props = GetPrpsInterfaces(type, BindingFlags.Public | BindingFlags.Instance).ToArray();

The Implementation of the replacing function:

static IEnumerable<PropertyInfo> GetPrpsInterfaces(Type type, BindingFlags flags)
{
      if (!type.IsInterface)
           return type.GetProperties(flags);

      return (new Type[] { type }).Concat(type.GetInterfaces()).SelectMany(i => i.GetProperties(flags));
}

I found here: GetProperties() to return all properties for an interface inheritance hierarchy

This worked for me.



标签: c# fastmember