I have the following method which sets the value for the given PropertyInfo
on the given TInstance
. This is to avoid the inefficiency of reflection.
public static Action<TInstance, object> CreateSetter<TInstance>(PropertyInfo propertyInfo, bool includeNonPublic = false)
{
var setMethod = propertyInfo.GetSetMethod(includeNonPublic);
var instance = Expression.Parameter(typeof(TInstance), "instance");
var value = Expression.Parameter(typeof(object), "value");
var valueCast = !propertyInfo.PropertyType.IsValueType
? Expression.TypeAs(value, propertyInfo.PropertyType)
: Expression.Convert(value, propertyInfo.PropertyType);
return Expression.Lambda<Action<TInstance, object>>(
Expression.Call(instance, setMethod, valueCast), instance, value).Compile();
}
So given the following model:
public sealed class PersonClass
{
public string Name {get; set;}
}
I can set the Name
using:
var person = new PersonClass();
var nameProp = person.GetType().GetProperties().Where(p => p.Name == "Name").First();
var nameSetter = CreateSetter<PersonClass>(nameProp);
nameSetter(person, "Foo");
This is all good however if I try the method with a struct
e.g.:
public struct PersonStruct
{
public string Name {get; set;}
}
The name is always null
. I suspect boxing/unboxing is biting me somehow.
In fact if I use FastMember
the same behavior exhibits when using:
PersonStruct person = new PersonStruct();
var accessor = TypeAccessor.Create(person.GetType());
accessor[person, "Name"] = "Foo";
However when I box the person
as object
then FastMember
is able to set the value correctly:
object person = new PersonStruct();
var accessor = TypeAccessor.Create(person.GetType());
accessor[person, "Name"] = "Foo";
Any ideas how I can handle this boxing inside the CreateSetter
for when TInstance
is a value type?