我正在创建一个 API,我的目标是公开一个可以像这样调用的方法:
Library.AddCallback<string>(Type.ChatMessage, GotMessage);
private void GotMessage(string message) {
//...
}
//or
Library.AddCallback<int>(Type.Number, GotNumber);
private void GotNumber(int number) {
//...
}
类型<int>
, <string>
可以是任何类型。
在库中,方法看起来像这样:
public void AddCallback<T1>(object type, Action<T1> callback) {
//...
}
问题是我不知何故想先将回调保存在方法调用之外(在列表中),然后再调用它。
理想情况下,我想做的是首先将其转换为一个对象,以便能够将其存储在 List<object>
中。然后将其投回 Action<T1>
.然而,似乎不可能将 T1 保存到变量中(除非执行 typeof(T1)
,这拒绝我使用它来将其强制转换回)。
我想如何调用它的示例(我从列表中得到了 type
和 data
):
((Action<type>)callback)(data)
最佳答案
我不确定如何 data
被键入。假设它的类型是 object
现在,您可以分解 Action<T>
至 Action<object>
并在其中进行转换:
private List<Action<object>> Callbacks = new List<Action<object>>();
public void AddCallback<T1>(object type, Action<T1> callback)
{
Callbacks.Add((data) => callback((T1)data));
}
public void FireCallback(object data)
{
Action<object> callback = GetCallback();
callback(data);
}
编辑:您已经将其标记为答案,但这是另一个将回调存储在类型集中的实现。
A CallbackHandler
存储类型化的回调列表:
public class CallbackHandler<T> : ICallbackHandler
{
private List<Action<T>> Callbacks = new List<Action<T>>();
public void AddCallback<T>(Action<T> callback)
{
Callbacks.Add(callback);
}
public void Callback(object data)
{
T typedData = (T)data;
foreach(var callback in Callbacks)
callback(typedData);
}
}
public interface ICallbackHandler
{
void Callback(object data);
}
然后你的上级Library
有这样的东西:
private Dictionary<Type, ICallbackHandler> AllCallbacks = new Dictionary<Type, ICallbackHandler>();
public void AddCallback<T>(Action<T> callback)
{
Type type = typeof(T);
ICallbackHandler handler;
if (!AllCallbacks.TryGetValue(type, out handler))
{
handler = new CallbackHandler<T>();
AllCallbacks[type] = handler;
}
CallbackHandler<T> typedHandler = (CallbackHandler<T>)handler;
typedHandler.AddCallback(callback);
}
public void FireCallback(object data)
{
Type type = data.GetType();
ICallbackHandler handler;
AllCallbacks.TryGetValue(type, out handler);
if (handler != null)
handler.Callback(data);
}
这是假设 data
的类型确定触发哪个回调。如果你需要在上面再放一层(基于 Type.ChatMessage
或 Type.Number
)应该不会太难。
关于c# - 使用未知类型参数 (Action<any>) 调用 Action,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16854956/