我正在创建一个API,我的目标是公开一个可以像这样调用的方法:
Library.AddCallback<string>(Type.ChatMessage, GotMessage);
private void GotMessage(string message) {
//...
}
//or
Library.AddCallback<int>(Type.Number, GotNumber);
private void GotNumber(int number) {
//...
}
Run Code Online (Sandbox Code Playgroud)
类型<int>,<string>可以是任何类型.
在库中,该方法看起来像这样:
public void AddCallback<T1>(object type, Action<T1> callback) {
//...
}
Run Code Online (Sandbox Code Playgroud)
问题是我想以某种方式首先在方法调用之外(在列表中)保存回调,然后才能调用它.
我理想的做法是首先将它转换为一个对象,以便能够将其存储在a中List<object>,然后再将其强制转换为Action<T1>.然而,似乎不可能将T1保存到变量中(除非通过typeof(T1)拒绝我使用它来将其转换回来).
我想怎么称呼它(在那里我得到实例type并data从列表中):
((Action<type>)callback)(data)
Run Code Online (Sandbox Code Playgroud)
我不确定怎么data打字.假设它object现在是类型,你可以分解Action<T>to 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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:您已经将它标记为答案,但这是另一个将回调存储在类型集中的实现.
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);
}
Run Code Online (Sandbox Code Playgroud)
然后你的更高级别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);
}
Run Code Online (Sandbox Code Playgroud)
这假设data确定要触发哪个回调的类型.如果你需要再添加一个级别(基于Type.ChatMessage或Type.Number),它应该不会太难.