Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FastMember ObjectReader doesn't work with inherited interfaces

Tags:

c#

fastmember

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?

like image 532
David S. Avatar asked Nov 16 '25 20:11

David S.


1 Answers

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.

like image 170
jr_gen Avatar answered Nov 19 '25 09:11

jr_gen