I'm replacing Reflection for setting property-values with LINQ using the SetProperty method below.
It works fine. However, when newValue comes from a SQL-query, it unfortunately can be System.DbNull.Value...
Is there any way to Check for DbNull in the LINQ-expression and set the value to NULL (type = object) if the value is DbNull, so I don't have to check for DbNull when calling the compiled expression ?
Note: I'm trying to replace reflection, so please don't advise me to use Reflection's SetValue instead.
Also, perhaps supplemential, is there any way to call a custom conversion function within the LINQ-expression ?
e.g. when newValue is of type string, but the target field is of type Guid or vice-versa? So I call MyChangeType instead of Expression.Convert ?
public static object MyChangeType(object objVal, System.Type t)
{
if (objVal == null || object.ReferenceEquals(objVal, System.DBNull.Value))
{
return null;
}
//getbasetype
System.Type tThisType = objVal.GetType();
bool bNullable = IsNullable(t);
if (bNullable)
{
t = System.Nullable.GetUnderlyingType(t);
}
if (object.ReferenceEquals(t, typeof(string)) && object.ReferenceEquals(tThisType, typeof(System.Guid)))
{
return objVal.ToString();
}
return System.Convert.ChangeType(objVal, t);
} // End Function MyChangeType
This is the code I have
// http://ift.tt/23dct2I
public static void SetProperty<T>(T target, string fieldName, object newValue)
{
// Class in which to set value
System.Linq.Expressions.ParameterExpression targetExp = System.Linq.Expressions.Expression.Parameter(typeof(T), "target");
// Object's type:
System.Linq.Expressions.ParameterExpression valueExp = System.Linq.Expressions.Expression.Parameter(typeof(object), "value");
// Expression.Property can be used here as well
System.Linq.Expressions.MemberExpression memberExp =
// System.Linq.Expressions.Expression.Field(targetExp, fieldName);
// System.Linq.Expressions.Expression.Property(targetExp, fieldName);
System.Linq.Expressions.Expression.PropertyOrField(targetExp, fieldName);
// BreakPoint: This is the Problem
{
System.Type type = memberExp.Type;
if (type.IsGenericType && object.ReferenceEquals(type.GetGenericTypeDefinition(), typeof(System.Nullable<>)))
{
System.Type undType = System.Nullable.GetUnderlyingType(type);
System.Console.WriteLine(undType);
}
}
System.Linq.Expressions.UnaryExpression conversionExp = System.Linq.Expressions.Expression.Convert(valueExp, memberExp.Type);
// End Of problem This is the Problem
System.Linq.Expressions.BinaryExpression assignExp =
//System.Linq.Expressions.Expression.Assign(memberExp, valueExp); // Without conversion
System.Linq.Expressions.Expression.Assign(memberExp, conversionExp);
//System.Action<TTarget, TValue> setter = System.Linq.Expressions.Expression
System.Action<T, object> setter = System.Linq.Expressions.Expression
.Lambda<System.Action<T, object>>(assignExp, targetExp, valueExp).Compile();
setter(target, newValue);
}
public class Person
{
public string Name { get; set; }
public Person Brother { get; set; }
public string Email { get; set; }
public string SnailMail;
public int Anumber;
public int? NullableNumber;
}
The problem illustrated
public static void LinqTest()
{
Person someOne = new Person() { Name = "foo", Email = "foo@bar.com", SnailMail="Snail" };
object obj = System.DBNull.Value;
SetProperty(someOne, "NullableNumber", obj);
}
Aucun commentaire:
Enregistrer un commentaire