gpt4 book ai didi

c# - 使用 ExpressionTree 将委托(delegate) (Action) 检索到索引器的 Setter

转载 作者:太空宇宙 更新时间:2023-11-03 14:15:43 25 4
gpt4 key购买 nike

我正在尝试创建委托(delegate)来访问任何 Property Get 和 Set 方法。

我发现以下代码(在这篇文章中:driis about deep properties)非常有效:

public static class Extractor<TObject> where TObject : class
{
public static DelegateAccessor<TObject, TValue> GetAccessorsDelegates<TValue>(Expression<Func<TObject, TValue>> expression)
{
Func<TObject, TValue> getter = expression.Compile();

ParameterExpression pObj = expression.Parameters[0];
ParameterExpression pValue = Expression.Parameter(typeof(TValue), "value");
BlockExpression setterBlock = Expression.Block(Expression.Assign(expression.Body, pValue));
Expression<Action<TObject, TValue>> setterExpression = Expression.Lambda<Action<TObject, TValue>>(setterBlock, pObj, pValue);
Action<TObject, TValue> setter = setterExpression.Compile();

return new DelegateAccessor<TObject, TValue>(getter,setter);
}
}

例如:当我从参数中的表达式创建 setter 时,我获得了如下这些 getter 和 setter 委托(delegate):

get : (t => t.ID)
set : (t, value) => { t.ID = value}

我的问题是像这样的索引器:

public object this[int id]

当我调用索引器的子属性时,没有问题。它工作正常,因为索引器,内部命名为“Item”,通过读取它来访问:

Extractor<MyObject>.DelegateAccessor(t => t.MySubTable[2].MyProperty)

表达式是:

t => t.MySubTable.get_Item(2).MyProperty

但我没有找到获取内部 setter 表达式的方法。我的目标是获得这样的东西:

(t, value) => { t.MySubTable.set_Item(2, value) }

但我不能像这样对 Lambda 使用赋值:

(t,v) => t.SubStrings[0] = v

我收到错误 CS0832:表达式树不能包含赋值运算符。

有没有一种方法可以编写 Lambda 表达式以便在表达式> 参数中找到“set_Item(2, value)”主体???

提前致谢,我知道这是一个很难的问题...

最佳答案

如果我没理解错的话,您想要一种与您已有的方法完全一样的方法,但它也适用于类似的东西

Extractor<MyObject>.DelegateAccessor(t => t.MySubTable[2])

如果是这样的话,像这样的东西应该可以工作:

public static DelegateAccessor<TObject, TValue> GetAccessorsDelegates<TValue>(
Expression<Func<TObject, TValue>> expression)
{
Func<TObject, TValue> getter = expression.Compile();

Action<TObject, TValue> setter = null;
ParameterExpression pValue = Expression.Parameter(typeof(TValue), "value");
ParameterExpression pObj = expression.Parameters[0];
if (expression.Body is MemberExpression)
{
Expression setterBlock = Expression.Assign(expression.Body, pValue);
Expression<Action<TObject, TValue>> setterExpression =
Expression.Lambda<Action<TObject, TValue>>(setterBlock, pObj, pValue);
setter = setterExpression.Compile();
}
else
{
var getterCall = expression.Body as MethodCallExpression;
if (getterCall != null)
{
var method = getterCall.Method;
if (method.IsSpecialName && method.Name.StartsWith("get_"))
{
var parameters = method.GetParameters()
.Select(p => p.ParameterType)
.Concat(new[] { method.ReturnType })
.ToArray();
var setterName = "set_" + method.Name.Substring(4);
var setterMethod =
method.DeclaringType.GetMethod(setterName, parameters);
var setterCall = Expression.Call(
getterCall.Object, setterMethod,
getterCall.Arguments.Concat(new[] { pValue }));
var setterExpression =
Expression.Lambda<Action<TObject, TValue>>(
setterCall, pObj, pValue);
setter = setterExpression.Compile();
}
}
}

return new DelegateAccessor<TObject, TValue>(getter, setter);
}

第一部分基本上是您拥有的方法的副本。第二部分检查表达式是否是对 getter 方法的调用,如果是,则将其替换为对 setter 方法的调用。有一些关于参数的工作,但除此之外,非常简单。

关于c# - 使用 ExpressionTree 将委托(delegate) (Action<TObject, TValue>) 检索到索引器的 Setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6628559/

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