问题
I have successfully assigned values to Properties and nested Properties using this function
private static void AssignValueToProperty(ObjectAccessor accessor, object value, string propertyLambdaString)
{
var index = propertyLambdaString.IndexOf('.');
if (index == -1)
{
accessor[propertyLambdaString] = value;
// problem above: throws Exception if assigning value to Nullable<T>
}
else
{
var property = propertyLambdaString.Substring(0, index);
accessor = ObjectAccessor.Create(accessor[property]);
AssignValueToProperty(accessor, value, propertyLambdaString.Substring(index + 1));
}
}
However, the assignment throws an InvalidCastException. How to assign nullable values instead using FastMember? For example
public class A
{
public double? SomeValue {get; set;}
}
...
var a = new A();
var accessor = ObjectAccessor.Create(a);
accessor["SomeValue"] = 100; // throws Exception, when assigning 100.0 it works???
回答1:
FastMember has nothing related to type conversion within it's toolbox, so this is the solution I came up with as Extension Method for FastMember ObjectAccessor
:
public static class FastMemberExtensions
{
public static void AssignValueToProperty(this ObjectAccessor accessor, string propertyName, object value)
{
var index = propertyName.IndexOf('.');
if (index == -1)
{
var targetType = Expression.Parameter(accessor.Target.GetType());
var property = Expression.Property(targetType, propertyName);
var type = property.Type;
type = Nullable.GetUnderlyingType(type) ?? type;
value = value == null ? GetDefault(type) : Convert.ChangeType(value, type);
accessor[propertyName] = value;
}
else
{
accessor = ObjectAccessor.Create(accessor[propertyName.Substring(0, index)]);
AssignValueToProperty(accessor, propertyName.Substring(index + 1), value);
}
}
private static object GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
Can be called this way:
var accessor = ObjectAccessor.Create(t); // t is instance of SomeType
accessor.AssignValueToProperty("Nested.Property", value); // t.Nested.Property = value
回答2:
FastMember is not going to convert types for you. 100 is an int literal, but the target property is of type decimal?. There is no implicit conversion from int to decimal? (or decimal). 100.0 is a Double literal which implicitly converts to decimal?, and thus the assignment will succeed.
public class A
{
public double? SomeValue { get; set; }
}
public static class Sample
{
public static void Go()
{
var a = new A();
var accessor = ObjectAccessor.Create(a);
accessor["SomeValue"] = 100.0; // succeeds
accessor["SomeValue"] = 100M; // succeeds
accessor["SomeValue"] = null; // succeeds
accessor["SomeValue"] = 100; // throws, can't convert from int to decimal?
}
}
If there is not an implicit conversion, you'll have to perform necessary conversions in your code.
Implicit conversions:
https://msdn.microsoft.com/en-us/library/y5b434w4.aspx
Explicit conversions:
https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx
来源:https://stackoverflow.com/questions/40306591/assign-value-to-nullablet-using-fastmember