0

我正在尝试构建一个库来简化 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;
    }

这不适用于值类型,因为它们被装箱为对象,因此它们不会被修改。例如:

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)的内部列表确实被修改,但调用外部的值没有被修改。

有谁知道克服这个限制的简单方法?无法修改 AddParameter 签名,与后期绑定调用一样,您无法提前知道参数的类型(以及在调用之前将调用的所有参数插入对象数组中的任何一种方式)

提前致谢。

4

3 回答 3

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

于 2008-11-12T10:19:00.643 回答
1

如果值在方法内部发生变化,则需要声明一个 temp( object) 变量以将 ( ref) 传递给方法,然后自行拆箱:

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

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

另请注意,C# 4.0在 COM 调用的上下文中提供了一些技巧来帮助解决此问题(其中ref object很常见 [当然还有dynamic后期绑定,正如 Jon 所指出的那样])。

于 2008-11-12T10:19:23.247 回答
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];

非常感谢您的帮助人们:)

于 2008-11-12T12:17:04.337 回答