【发布时间】:2011-05-21 02:03:41
【问题描述】:
据我所知,没有办法与表达式树中的引用类型进行交互。 (例如,什么都不会发出 stind.* 或 ldind.* 操作码)。
我正在做一个重写器来解决这个烦恼。因为我正在构建一个新类型,它的方法体被委托调用替换(为了解决CompileToMethod 只能执行不能与新成员交互的静态方法的事实)。对于 by-ref 和 out 参数,我想我会用StrongBox<T> 替换它们的用法。
所以,如果我遇到一个签名看起来像这样的方法::
public class SomeClass
{
public virtual bool SomeMethod(string arg1,ref int arg2)
{
}
}
我生成的覆盖、callbase 方法和委托字段将如下所示::
public class SomeClass<1> : SomeClass
{
private static bool SomeMethod<0>(
SomeClass target,string arg1,StrongBox<int> arg2)
{
return call target.SomeMethod(arg1,ref arg2.Value)
}
private Func<SomeClass,string,StrongBox<int>,bool> <0>SomeMethod;
public override bool SomeMethod(string arg1,ref int arg2)
{
StrongBox<int> box = new StrongBox<int>();
box.Value = arg2;
bool retVal = <0>SomeMethod.Invoke(this,arg1,box);
arg2 = box.Value;
return retVal;
}
}
然而,执行这种转换的代码相当多,对于每个参数它都会引入很多复杂性。当我执行box.Value = arg2 的设置时会容易得多,如果我可以执行&box.Value = &arg2 之类的操作,即按原样将其地址分配给arg2 的地址。这样,当委托对值字段执行突变时,就会转发更改。这样做意味着我不需要有一个变量来保存返回值,也不需要执行引用值更新。
另外,如果有一种方法可以使用表达式树执行按引用分配的语义,我当然会全神贯注。
【问题讨论】:
-
这让我想起了 Eric Lippert 的Ref Class。
标签: c# clr reflection.emit