将通用委托 Action<T> 转换为 Action<string>
Casting generic delegate Action<T> to Action<string>
我正在努力实施 pub/sub 缓存使用模式。以下class假设用于发布任何类型的数据。订阅者可以在事件上附加 Action
T
的回调。但是如果不使 class 通用,我就无法在 class 级别创建通用事件,我不想这样做。因此,我尝试使用 JsonSerializer
将值来回转换为字符串,如下所示。
public class CacheNotification
{
public Action<string> CachePublished;
public Task Publish<T>(T value)
{
var json = JsonSerializer.Serialize(value);
OnCachePublished(json);
return Task.CompletedTask;
}
public Task Subscribe<T>(Action<T> callback)
{
Action<string> newCallback = (string json) =>
callback(JsonSerializer.Deserialize<T>(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
protected virtual void OnCachePublished(string value)
{
if(CachePublished != null){
CachePublished.Invoke(value);
}
}
}
所以问题出在订阅方法上,我尝试的转换仅适用于 Action
字符串。它在 Action
int
或 Action
object
上失败
public Task Subscribe<T>(Action<T> callback)
{
Action<string> newCallback = (string json) =>
callback(JsonSerializer.Deserialize<T>(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
这是我用过的一个测试。第二个订阅者失败
Action<string> sub1Callback = msg =>
{
sub1Counter++;
};
Action<int> sub2Callback = num =>
{
sub2Counter++;
};
var sub1 = await cache.Subscribe(sub1Callback);
var sub2 = await cache.Subscribe(sub2Callback);
await cache.Publish("Value1");
Assert.Equal(1, sub1Counter);
Assert.Equal(1, sub2Counter);
你的问题在这里:
Action sub2Callback = num =>
之后
await cache.Publish("Value1");
你的:
public Task Subscribe<T>(Action<T> callback)
{
Action newCallback = (string json) =>
callback(JsonSerializer.Deserialize(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
尝试将“Value1”反序列化为整数,但正确地失败了。做不到。
尝试发送整数值而不是“Value1”,它应该可以工作。
另一种方法是重构您的 Subscribe 方法,使其独立于给定类型,但我猜这不能按照您的意图来完成。
我正在努力实施 pub/sub 缓存使用模式。以下class假设用于发布任何类型的数据。订阅者可以在事件上附加 Action
T
的回调。但是如果不使 class 通用,我就无法在 class 级别创建通用事件,我不想这样做。因此,我尝试使用 JsonSerializer
将值来回转换为字符串,如下所示。
public class CacheNotification
{
public Action<string> CachePublished;
public Task Publish<T>(T value)
{
var json = JsonSerializer.Serialize(value);
OnCachePublished(json);
return Task.CompletedTask;
}
public Task Subscribe<T>(Action<T> callback)
{
Action<string> newCallback = (string json) =>
callback(JsonSerializer.Deserialize<T>(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
protected virtual void OnCachePublished(string value)
{
if(CachePublished != null){
CachePublished.Invoke(value);
}
}
}
所以问题出在订阅方法上,我尝试的转换仅适用于 Action
字符串。它在 Action
int
或 Action
object
public Task Subscribe<T>(Action<T> callback)
{
Action<string> newCallback = (string json) =>
callback(JsonSerializer.Deserialize<T>(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
这是我用过的一个测试。第二个订阅者失败
Action<string> sub1Callback = msg =>
{
sub1Counter++;
};
Action<int> sub2Callback = num =>
{
sub2Counter++;
};
var sub1 = await cache.Subscribe(sub1Callback);
var sub2 = await cache.Subscribe(sub2Callback);
await cache.Publish("Value1");
Assert.Equal(1, sub1Counter);
Assert.Equal(1, sub2Counter);
你的问题在这里:
Action sub2Callback = num =>
之后
await cache.Publish("Value1");
你的:
public Task Subscribe<T>(Action<T> callback)
{
Action newCallback = (string json) => callback(JsonSerializer.Deserialize(json));
CachePublished += newCallback;
return Task.CompletedTask;
}
尝试将“Value1”反序列化为整数,但正确地失败了。做不到。
尝试发送整数值而不是“Value1”,它应该可以工作。
另一种方法是重构您的 Subscribe 方法,使其独立于给定类型,但我猜这不能按照您的意图来完成。