C# 使用DLR调用带有ref参数的方法

C# 使用DLR调用带有ref参数的方法,c#,dynamic,C#,Dynamic,尝试调用使用ref参数的示例方法: public void RefTest(ref int i) { Console.WriteLine(i); i = 18; } 利用DLR: var prog = new Program(); var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember( CSharpBinderFlags.ResultDiscarded, "RefTest", null,

尝试调用使用ref参数的示例方法:

public void RefTest(ref int i)
{
    Console.WriteLine(i);
    i = 18;
}
利用DLR:

var prog = new Program();
var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
    CSharpBinderFlags.ResultDiscarded,
    "RefTest", null, typeof(Program),
    new CSharpArgumentInfo[]{
        CSharpArgumentInfo.Create(0,null),
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsRef,null)
    }
);
ParameterExpression p = Expression.Parameter(typeof(int));
Expression dyn = Expression.Dynamic(binder, typeof(object), Expression.Constant(prog), p);
var lam = Expression.Lambda<Action<int>>(dyn, p).Compile();
lam(9); //RuntimeBinderException
var prog=new Program();
var binder=Microsoft.CSharp.RuntimeBinder.binder.InvokeMember(
CSharpBinderFlags.resultdiscared,
“RefTest”,空,类型(程序),
新CSharpArgumentInfo[]{
CSharpArgumentInfo.Create(0,null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsRef,null)
}
);
ParameterExpression p=表达式.参数(typeof(int));
表达式dyn=表达式动态(活页夹、类型(对象)、表达式常量(程序)、p);
var lam=Expression.Lambda(dyn,p).Compile();
林(9),//RuntimeBinderException
但是,代码失败,RuntimeBinderException无法将int转换为ref int。如何修复它

我试图模仿以下代码:

dynamic prog = new Program();
Action<int> lam = i => prog.RefTest(ref i);
lam(9);
dynamic program = ...;
program.RefTest(ref myInt);
Expression programExpr = Expression.Constant(program);
var binder = Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded | CSharpBinderFlags.InvokeSimpleName, "Bla", null, typeof (Program),
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsRef, null) });
var intParam = Expression.Parameter(typeof (int).MakeByRefType(), "x");
Expression methodCall = Expression.Dynamic(binder, typeof (void), programExpr, intParam);
var expr = Expression.Lambda<RefAction<int>>(methodCall, intParam).Compile();
expr(ref myInt);
dynamic prog=新程序();
动作lam=i=>程序参考测试(参考i);
林(9),;
我必须使用DLR而不是反射,因为提供的对象(
prog
)可能是动态的。

如果我没有错的话。参考 Alexandra Rusina在链接线程和中的回答

尝试以下操作(无法编译):


简单动态不支持ref/out。因此,显然,在表达式中尝试同样的方法也不会奏效。

我重现了您的问题,并发现了有关代码的一些潜在问题。为了解释,我将从如何解释您实际尝试执行的操作开始,即运行以下代码:

dynamic prog = new Program();
Action<int> lam = i => prog.RefTest(ref i);
lam(9);
dynamic program = ...;
program.RefTest(ref myInt);
Expression programExpr = Expression.Constant(program);
var binder = Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded | CSharpBinderFlags.InvokeSimpleName, "Bla", null, typeof (Program),
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsRef, null) });
var intParam = Expression.Parameter(typeof (int).MakeByRefType(), "x");
Expression methodCall = Expression.Dynamic(binder, typeof (void), programExpr, intParam);
var expr = Expression.Lambda<RefAction<int>>(methodCall, intParam).Compile();
expr(ref myInt);
请注意,上面的代码工作正常,并运行该方法

这里有几点需要注意:

  • 程序
    变量是一个常量
  • 该方法返回
    void
  • 我们应该能够通过引用传入任何整数
您的问题中有一些与此不符的地方:

  • 您的
    表达式.Dynamic
    调用告诉方法返回
    对象
    。相反,它应该返回
    typeof(void)
  • 您的
    表达式.Lambda
    调用将委托类型指定为
    操作。参数的类型应为
    ref int
    。要解决这个问题,应该有一个
    操作
    ,它具有
    ref
    参数<代码>委托无效重构(参考T arg1)
这让我想到了以下代码:

dynamic prog = new Program();
Action<int> lam = i => prog.RefTest(ref i);
lam(9);
dynamic program = ...;
program.RefTest(ref myInt);
Expression programExpr = Expression.Constant(program);
var binder = Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded | CSharpBinderFlags.InvokeSimpleName, "Bla", null, typeof (Program),
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsRef, null) });
var intParam = Expression.Parameter(typeof (int).MakeByRefType(), "x");
Expression methodCall = Expression.Dynamic(binder, typeof (void), programExpr, intParam);
var expr = Expression.Lambda<RefAction<int>>(methodCall, intParam).Compile();
expr(ref myInt);

虽然是关于
out
而不是
ref
,但同样的问题适用,同样的答案解决,除非我遗漏了进一步的区别。@Jon错了。这使用DLR,而不是反射。如果这是您期望的答案,那么将参数类型设置为
typeof(int).MakeByRefType()
也没有帮助。@illand4另一个示例使用表达式树的方式与您相同。您是否将DLR与表达式的运行时创建混为一谈?@Bas Duh,我是-您没有看到
Expression.Dynamic
?@IllidanS4只是确保这是有意的。我如何理解这个问题是参数是强类型的。这只是OP要求的动态调用…@因为你可能是对的。我不确定我是否遗漏了真正的问题。我相信这是一个XY问题。在阅读了您的答案后,我相信ref和dynmaic不能很好地协同工作。感谢您的努力,但我需要使用DLR,以防对象是动态的(ref和out参数在动态对象上受支持)。@illdans4这就是为什么我提到了由于运行时错误而无法执行此操作的可能性。我希望你能解决它,但这感觉像是无法解决的事情。