Reputation: 7440
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
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