【发布时间】:2020-07-22 09:46:55
【问题描述】:
过去提出的类似问题:
- Convert Action<T> to Action<object>
- Expose Action<T> as Action<object>
- How to cast object to Action<T>
所有人都找到了将Action<T> myActionT 包装成匿名new Action<object>(o => myActionT((T)o)); 的解决方案
我的用例是初始的类型化 lambda 是一个数据订阅回调,将其包装成一个匿名回调意味着我无法使用原始 Action<T> 取消订阅。
我将其缩小到这个样板示例:
internal class Demo
{
public class Dispatcher
{
private List<Action<object>> callbacks = new List<Action<object>>();
public void Subscribe<T>(Action<T> cbk)
{
callbacks.Add(cbk); // <- compile error, Action<T> is contravariant
}
public void Unsubscribe<T>(Action<T> cbck)
{
callbacks.Remove(cbck); // <- compile error
}
}
private static void Handler(int v) {}
private static void Handler(string v) {}
public static void Main()
{
var dispatcher = new Dispatcher();
dispatcher.Subscribe<int>(Handler);
dispatcher.Subscribe<string>(Handler);
dispatcher.Unsubscribe<int>(Handler);
}
}
当然我可以重载Subscribe(因为我实际上只需要值类型)
是否有更好/更优雅的方法来正确跟踪通用 Action 回调?
稍后编辑:添加有关我的用例的更多详细信息:
- 我包装了键值(字符串)更新的数据馈送
- 客户端可以订阅字段,并且可以选择接收从字符串转换为其他类型的值
(我用
TypeDescriptor.GetConverter(type).ConvertFromString(fieldValue)来处理转化)
例如:
Subscribe<decimal>("price", (decimal px) => { /* do smthg with price*/ })
Subscribe<bool>("opened", (bool opened) => { ... })
Subscribe<string>("code", (string code) => { ... })
我觉得我目前的方法(函数指针/委托,跟踪订阅类型)陷入了困境
但我没有找到更直接的方法来实现这一点(除了用我需要的类型重载Subscribe,这可能是明智的 KISS 选择)
【问题讨论】:
-
“因为我实际上只需要值类型”。
string不是值类型。 -
除了订阅/取消订阅之外,您还打算如何处理
callbacks。你也看过events吗? -
我添加了一些关于我如何使用
callbacks的更多细节@ -
@AlinMotogna - 您是否考虑过为此使用 Microsoft 的 Rx?
-
直到现在才听说过,对于我的简单用例来说看起来很重,但我会明确地研究它。谢谢!