params可用于调用具有强类型参数的方法吗?

时间:2014-12-02 05:16:09

标签: c# delegates

我有一个根据网络状态调用委托的方法。该方法必须决定在何处调用该方法(服务器,客户端)。为了使其适用于任何方法,我已经定义了以下代理:

public delegate void NetworkCall( params object[] args );

这将采用任何参数,但仅适用于具有完全相同签名的方法。这导致了这个问题:

protected virtual void DoNetowrkMove( params object[] args )
{
    destination = ( Vector3 )args[0];
}

这不是一个理想的解决方案。是否有可能"解包" ' args'中的对象进入更安全的方法调用?例如:

protected virtual void DoNetowrkMove( Vector3 newDestination )
{
    destination = newDestination;
}

1 个答案:

答案 0 :(得分:1)

我不确定在这里完全掌握用例。似乎更灵活的解决方案将涉及对发送的数据进行一些真正的序列化/反序列化,这将允许端到端的类型安全通信。

尽管如此,虽然代表们不允许您直接尝试做什么,但您可以创建一个通用方法来自动完成大部分工作:

delegate void Callback(params object[] args);

static void Method1(params string[] args) { }

static Callback Wrap<T>(Action<T[]> action)
{
    return (Callback)((object[] args) => action(args.Cast<T>().ToArray()));
}

static void Main(string[] args)
{
    Callback callback1 = Wrap<string>(Method1);
}

这会将args数组的每个元素强制转换为指定的类型。当然,这要求被包装的方法具有用于其唯一参数的数组,例如,一个params数组。要处理更类似于您的具体示例的内容,您可以这样做:

static void Method2(string arg) { }

static Callback Wrap<T>(Action<T> action)
{
    return (Callback)((object[] args) => action((T)args[0]));
}

static void Main(string[] args)
{
    Callback callback2 = Wrap<string>(Method2);
}

与.NET泛型委托类型ActionFunc一样,您必须为每个参数计数委托声明一个特定的包装器方法。以上只适用于一个参数。如果您有两个参数的示例,则需要添加:

static void Method3(string arg1, bool arg2) { }

static Callback Wrap<T1, T2>(Action<T1, T2> action)
{
    return (Callback)((object[] args) => action((T1)args[0], (T2)args[1]));
}

static void Main(string[] args)
{
    Callback callback3 = Wrap<string, bool>(Method3);
}

等等。写这些小包装纸是否真的值得,当然取决于你使用它们的程度。我会说在第三次或第四次回调之后,你可能觉得它值得。

当然,我仍然认为使用基于序列化的方法可能会更好。但这是一个不同的问题。 :)