我想在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签名,因为对于后期绑定调用,您无法事先知道参数的类型(以及在进行调用之前插入对象数组内的调用的所有参数的方式)

提前致谢。

有帮助吗?

解决方案

如果值正在改变方法中的,则需要声明temp( object )变量以传递( ref )到方法,然后自己拆箱:

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

请注意,这不允许您在事件发生后更新值。像事件或回调之类的东西可能是将更改传递回调用者的另一种方法。

另请注意,C#4.0在COM调用的上下文中有一些技巧可以帮助解决这个 (其中 ref object 是如此常见[当然还有动态用于后期绑定,如Jon所指出的那样。)。

其他提示

您的方法无论如何都不会改变 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

好的,感谢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];

非常感谢你的帮助:)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top