我有一个根据网络状态调用委托的方法。该方法必须决定在何处调用该方法(服务器,客户端)。为了使其适用于任何方法,我已经定义了以下代理:
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;
}
答案 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泛型委托类型Action
和Func
一样,您必须为每个参数计数委托声明一个特定的包装器方法。以上只适用于一个参数。如果您有两个参数的示例,则需要添加:
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);
}
等等。写这些小包装纸是否真的值得,当然取决于你使用它们的程度。我会说在第三次或第四次回调之后,你可能觉得它值得。
当然,我仍然认为使用基于序列化的方法可能会更好。但这是一个不同的问题。 :)