本文介绍了如何使用Expression.Assign选择器与目标对象类型一般分配属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用表达式选择器来将属性从一种类型的对象分配给另一种类型的属性。这是迄今为止的代码:

I am trying to use an Expression selector to generically assign properties from one type of object to another where the properties are of various types. This is the code I have so far:

var type1 = new Type1();
var type2 = new Type2();

...

var propMap = new List<Tuple<Expression<Func<Type1, object>>, Expression<Func<TradeStaticAttributesItemModel, object>>>>
    {
        new Tuple<Expression<Func<Type1, object>>, Expression<Func<Type2, object>>>(x => x.Prop1, x => x.Prop1),
        new Tuple<Expression<Func<Type1, object>>, Expression<Func<Type2, object>>>(x => x.Prop2, x => x.Prop2)
    };

foreach (var prop in propMap)
{
    if (prop.Item1.Compile()(type1) != prop.Item2.Compile()(type2))
    {
        ParameterExpression valueParameterExpression = Expression.Parameter(prop.Item2.Body.Type);
        var assign = Expression.Lambda<Action<Type1, object>>(Expression.Assign(prop.Item1.Body, valueParameterExpression), prop.Item1.Parameters.Single(), valueParameterExpression);
        Action<Type1, object> setter = assign.Compile();
        setter(type1, prop.Item2.Compile()(type2));
    }
}

但是,我是错误类型System.String的ParameterExpression不能用于System.Object类型的委托参数,当属性类型为字符串。我想这也会发生在除对象之外的任何其他类型。任何想法如何使此代码适用于这种情况?

However, I am However, I'm getting the error "ParameterExpression of type 'System.String' cannot be used for delegate parameter of type 'System.Object'" when the type of property is a string. I guess this would also happen for any other type other than object. Any idea how to make this code work for such a situation?

我发现一个潜在的答案

I found a potential answer here using Expression.Convert, but I can't get it to work.

推荐答案

好的,我使用以下代码:

OK, I got this working with the following code:

var type1 = new Type1();
var type2 = new Type2();

...

var propMap = new List<Tuple<Expression<Func<Type1, object>>, Expression<Func<TradeStaticAttributesItemModel, object>>>>
    {
        new Tuple<Expression<Func<Type1, object>>, Expression<Func<Type2, object>>>(x => x.Prop1, x => x.Prop1),
        new Tuple<Expression<Func<Type1, object>>, Expression<Func<Type2, object>>>(x => x.Prop2, x => x.Prop2)
    };

foreach (var prop in propMap)
{
    if (prop.Item1.Compile()(type1) != prop.Item2.Compile()(type2))
    {
        ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object));

        // This handles nullable types
        Expression targetExpression = prop.Item1.Body is UnaryExpression ? ((UnaryExpression)prop.Item1.Body).Operand : prop.Item1.Body;

        var assign = Expression.Lambda<Action<Type1, object>>(
            Expression.Assign(targetExpression, Expression.Convert(valueParameterExpression, targetExpression.Type)),
            prop.Item1.Parameters.Single(),
            valueParameterExpression);

        Action<Type1, object> setter = assign.Compile();
        setter(type1, prop.Item2.Compile()(type2));
    }
}

这适用于可空类型(已注释)。我现在知道Expression,但是如果有任何改进的代码,请随时提出建议!

This works for nullable types (as commented). I now know Expression, but if anyone has any improvements for this code, please feel free to suggest them!

这篇关于如何使用Expression.Assign选择器与目标对象类型一般分配属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!