Rand Random
Rand Random

Reputation: 7440

Fastmember access non public properties

I wanted to replace my reflection index accessor with FastMember (https://www.nuget.org/packages/FastMember/) but stumbled across the following problem.

I have the following setup:

class Program
{
    static void Main(string[] args)
    {
        var d = new DerivedClass
        {
            Name = "Derived Name Property",
            BaseName = "Base Name Property",
            BaseInternalName = "Base Internal Name Property",
        };

        Console.WriteLine(d["Name"]);
        Console.WriteLine(d["BaseName"]);
        Console.WriteLine(d["BaseInternalName"]);
        Console.ReadLine();
    }
}

public abstract class BaseClass
{
    public object this[string propertyName]
    {
        get
        {
            var x = GetTypeAccessor();
            return x[this, propertyName];
        }
        set
        {
            var x = GetTypeAccessor();
            x[this, propertyName] = value;
        }
    }

    protected abstract TypeAccessor GetTypeAccessor();

    public string BaseName { get; set; }
    internal string BaseInternalName { get; set; }
}
public class DerivedClass : BaseClass
{
    public string Name { get; set; }

    private TypeAccessor _typeAccessor;

    protected override TypeAccessor GetTypeAccessor()
    {
        if (_typeAccessor == null)
            _typeAccessor = TypeAccessor.Create(this.GetType(), true);

        return _typeAccessor;
    }
}

With this I am getting the following exception, on the line Console.WriteLine(d["BaseInternalName"]);

An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in FastMember_dynamic

Innerexception is null.

According to nuget https://www.nuget.org/packages/FastMember/ there should be support for accessing non public properties, since version 1.0.0.8:

Another thing I noticed is that in nuget it is saying that 1.0.0.11 is the newest version, but the dll that gets downloaded to my computer on Install-Package FastMember has the version 1.0.0.9, maybe marc https://stackoverflow.com/users/23354/marc-gravell sees this and can fix it. :)

Upvotes: 3

Views: 3835

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

Digging into the code inside TypeAccessor (or more precisely the derived DelegateAccessor), you can see that the allowNonPublicAccessors is used as a value to get non-public property getter / setter, not a non-public property / field.

This is the relevant piece of code (inside the TypeAccessor.WriteMapImpl):

PropertyInfo prop = (PropertyInfo)member;
MethodInfo accessor;
if (prop.CanRead && (accessor = (isGet ? prop.GetGetMethod(allowNonPublicAccessors) : prop.GetSetMethod(allowNonPublicAccessors))) != null)

Also, you can see CreateNew only tries to access public instance fields / properties:

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

Therefor, you cannot access any non-public fields/properties via the TypeAccessor object.

Upvotes: 2

Related Questions