我想在C#中构建一个用于简化后期绑定调用的库,并且我在使用参考参数时遇到了麻烦。我有以下方法来添加方法调用中使用的参数
public IInvoker AddParameter(ref object value)
{
//List<object> _parameters = new List<object>();
_parameters.Add(value);
//List<bool> _isRef = new List<bool>();
_isRef.Add(true);
return this;
}
这对值类型不起作用,因为它们被装箱作为对象,因此它们不会被修改。 E.g:
int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);
这不起作用。后期绑定调用成功,保存参数(_parameters)的内部List确实被修改,但不是调用之外的值。
有谁知道克服这种限制的简单方法? 无法修改AddParameter签名,因为对于后期绑定调用,您无法事先知道参数的类型(以及在进行调用之前插入对象数组内的调用的所有参数的方式)
提前致谢。
答案 0 :(得分:1)
您的方法无论如何都不会改变value
- 为什么要通过引用传递它?这可能有意义,但对我来说并不是很清楚。请注意,您提供的示例代码无论如何都不会编译,因为ref
参数必须与参数完全相同。
(另外,你是否知道C#4.0和.NET 4.0将内置支持后期绑定?有可能语言集成版本比只有库的版本更容易使用。你确定吗?现在值得在图书馆上花时间吗?)
编辑:您提供的代码实际上无法编译。你没有获得ref
参数的装箱,正是因为参数和参数类型必须完全相同。以下是一些示例代码来证明它:
public class Test
{
static void Main()
{
int i;
Foo(ref i); // Won't compile - error CS1502/1503
}
static void Foo(ref object x)
{
}
}
如果您当前的代码正在进行编译,那么这不是您在问题中提供的代码。也许你有AddParameter
的另一个重载接受ref int
?
答案 1 :(得分:1)
如果值正在改变方法中的,则需要声明temp(object
)变量以将(ref
)传递给方法,并将其取消装箱事后你自己:
int i = 3;
//...
object obj = i;
Foo(ref obj);
i = (int)obj;
请注意,这不允许您在事件发生后更新值。像事件或回调之类的东西可能是将更改传递回调用者的另一种方法。
另请注意,在COM调用的上下文中,C#4.0有一些技巧可以帮助解决这个 的问题(其中ref object
非常常见[加上当然dynamic
}绑定,如Jon所说]。
答案 2 :(得分:0)
好的,感谢Jon Skeet的更正和Mark Gravell代码,我想出了这个界面:
//This will be created with a factory
IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
int param1 = 2;
object paramObj = param1;
invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");
param1 = (int)invoker.Parameters[0];
不完全像我想象的那样,但是我之前的界面更简单,更易读:
IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
int refValue = 10;
object[] args = Args.Build(refValue);
invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);
refValue = (int)args[0];
非常感谢你的帮助:)