C# 使用IL通过ref指定字段是否合法?
据我所知,在表达式树中没有与引用类型交互的方法。(例如,任何东西都不会发出C# 使用IL通过ref指定字段是否合法?,c#,clr,reflection.emit,C#,Clr,Reflection.emit,据我所知,在表达式树中没有与引用类型交互的方法。(例如,任何东西都不会发出stind.*或ldind.*操作码)。 我正在编写一个重写程序来避开这个麻烦。因为我正在构建一个新类型,它将方法体替换为委托调用(以避免CompileToMethod只能执行不能与新成员交互的静态方法)。对于by-ref和out参数,我认为应该用StrongBox替换它们的用法 因此,如果我遇到一个签名如下的方法: public class SomeClass { public virtual bool Some
stind.*
或ldind.*
操作码)。
我正在编写一个重写程序来避开这个麻烦。因为我正在构建一个新类型,它将方法体替换为委托调用(以避免CompileToMethod
只能执行不能与新成员交互的静态方法)。对于by-ref和out参数,我认为应该用StrongBox
替换它们的用法
因此,如果我遇到一个签名如下的方法:
public class SomeClass
{
public virtual bool SomeMethod(string arg1,ref int arg2)
{
}
}
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;
}
}
我生成的覆盖、callbase方法和委托字段如下所示:
public class SomeClass
{
public virtual bool SomeMethod(string arg1,ref int arg2)
{
}
}
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;
}
}
公共类SomeClass:SomeClass
{
私有静态布尔方法(
SomeClass目标,字符串arg1,保险箱arg2)
{
返回调用target.SomeMethod(arg1,ref arg2.Value)
}
私有函数方法;
公共重写bool SomeMethod(字符串arg1,ref int arg2)
{
strong框=新的strong框();
box.Value=arg2;
bool retVal=SomeMethod.Invoke(this,arg1,box);
arg2=box.Value;
返回返回;
}
}
然而,执行这种转换需要大量代码,因为每个参数都会带来很多复杂性。如果我可以像&box.Value=&arg2
那样将其地址分配给arg2的地址,那么在执行box.Value=arg2
的设置时会容易得多。这样,当委托在值字段上执行变异时,更改将被转发。这样做意味着我不需要有一个变量来保存返回值,也不需要执行参考值更新
或者,如果有一种方法可以使用表达式树执行按引用赋值语义,我当然洗耳恭听 不确定我是否真的理解,但也许这是一个解决方案:
class Program
{
public class SomeClass
{
private readonly int _n;
public SomeClass(int n) { _n = n; }
public virtual bool SomeMethod(string arg1, ref int arg2) {
if (String.IsNullOrWhiteSpace(arg1)) return false;
arg2 += arg1.Length + _n;
return true;
}
}
private delegate bool SomeDelegate(SomeClass that, string arg1, ref int arg2);
static void Main(string[] args) {
var instance = Expression.Parameter(typeof (SomeClass), "that");
var arg1Param = Expression.Parameter(typeof(string), "arg1");
var arg2Param = Expression.Parameter(typeof (int).MakeByRefType(), "arg2");
var someMethodInfo = typeof (SomeClass).GetMethod("SomeMethod");
var lambda = Expression.Lambda<SomeDelegate>(Expression.Call(instance, someMethodInfo, arg1Param, arg2Param), instance, arg1Param, arg2Param);
var someDelegate =lambda.Compile();
var myClass = new SomeClass(2);
var arg1 = "yup";
var arg2 = 1;
var result = someDelegate(myClass, arg1, ref arg2);
if(arg2 != 6) throw new Exception("Bad!");
Console.WriteLine("works...");
}
}
类程序
{
公共类
{
私有只读int;
公共类(int n){u n=n;}
公共虚拟布尔方法(字符串arg1,引用int arg2){
if(String.IsNullOrWhiteSpace(arg1))返回false;
arg2+=arg1.长度+\n;
返回true;
}
}
私有委托bool SomeDelegate(SomeClass,字符串arg1,ref int arg2);
静态void Main(字符串[]参数){
var instance=Expression.Parameter(typeof(SomeClass),“that”);
var arg1Param=Expression.Parameter(typeof(string),“arg1”);
var arg2Param=Expression.Parameter(typeof(int).MakeByRefType(),“arg2”);
var someMethodInfo=typeof(SomeClass).GetMethod(“SomeMethod”);
var lambda=Expression.lambda(Expression.Call(instance,someMethodInfo,arg1Param,arg2Param),instance,arg1Param,arg2Param);
var someDelegate=lambda.Compile();
var myClass=新的SomeClass(2);
var arg1=“是”;
var arg2=1;
var result=someDelegate(myClass,arg1,ref arg2);
如果(arg2!=6)抛出新异常(“坏!”);
控制台。WriteLine(“工作…”);
}
}
我认为最重要的一点是
typeof(int)。MakeByRefType()
这让我想起了Eric Lippert的。