gpt4 book ai didi

c# - 在编译时不知道目标类型的情况下设置属性

转载 作者:行者123 更新时间:2023-11-30 13:48:54 28 4
gpt4 key购买 nike

我想在编译时不知道对象类型的情况下设置对象的属性值;我希望它快(即不要每次都使用反射);我知道属性名称和类型。

最快的方法 (afaik) 是使用委托(delegate);所以这就是我到目前为止所拥有的:

class User // this is an example.. Assume I don't know which type this is.
{
public string Name {get;set;}
}

public static Action<object, object> CreatePropertySetter(Type targetType, string propertyName)
{
ParameterExpression targetObjParamExpr = Expression.Parameter(targetType);
ParameterExpression valueParamExpr = Expression.Parameter(targetType.GetProperty(propertyName).PropertyType);

MemberExpression propertyExpr = Expression.Property(targetObjParamExpr, propertyName);

BinaryExpression assignExpr = Expression.Assign(targetObjParamExpr, valueParamExpr);

Action<object, object> result = Expression.Lambda<Action<object, object>>(assignExpr, targetObjParamExpr, valueParamExpr).Compile();
return result;
}

然后我会打这个电话:

User user = new User();
var userNameSetter = CreatePropertySetter(user.GetType(), "Name");
userNameSetter(user, "Bob");

但是,它不喜欢我传递 User 类型对象而不是 Object 的事实,并且失败并显示“'User' 类型的 ParameterExpression 不能用于'System.Object 类型的委托(delegate)参数”。

我是表达式树的新手,所以在这里有点迷路。为什么不能将 User 转换为 object ?我需要在某处类型转换吗?

“ Action ”看起来也不太好;只返回一个接受参数(用户用户,字符串属性值)的委托(delegate)会更好。同样,不确定如何实现。实际上,我已经尝试过使用 Delegate.CreateDelegate,但它使用 .Invoke() 方法调用,这很慢(这是唯一的方法吗?);与 Expression.Lambda(非泛型)相同。

有什么想法吗?

此外,是否有关于表达式树的良好(比 msdn 更好)的文档? msdn版本确实缺乏细节。

最佳答案

如果你想使用Expression,那么:Convert...

static void Main()
{
var setter = CreatePropertySetter(typeof (User), "Name");
var obj = new User();
setter(obj, "Fred");
}
public static Action<object, object> CreatePropertySetter(Type targetType, string propertyName)
{
var target = Expression.Parameter(typeof (object), "obj");
var value = Expression.Parameter(typeof (object), "value");
var property = targetType.GetProperty(propertyName);
var body = Expression.Assign(
Expression.Property(Expression.Convert(target, property.DeclaringType), property),
Expression.Convert(value, property.PropertyType));

var lambda = Expression.Lambda<Action<object, object>>(body, target, value);
return lambda.Compile();
}

但是!你可能想看看 FastMember (也可在 NuGet 上获得),它非常方便地为您包装了所有(并使用原始 IL 来实现愚蠢的疯狂)。

如果你想使用有类型的委托(delegate),你需要提前知道类型。如果您知道类型,您可以添加一些泛型:

static void Main()
{
var setter = CreatePropertySetter<User,string>("Name");
var obj = new User();
setter(obj, "Fred");
}
public static Action<TType, TValue> CreatePropertySetter<TType, TValue>(string propertyName)
{
var target = Expression.Parameter(typeof (TType), "obj");
var value = Expression.Parameter(typeof (TValue), "value");
var property = typeof(TType).GetProperty(propertyName);
var body = Expression.Assign(
Expression.Property(target, property),
value);

var lambda = Expression.Lambda<Action<TType, TValue>>(body, target, value);
return lambda.Compile();
}

关于c# - 在编译时不知道目标类型的情况下设置属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10760139/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com