我需要一个由字符串索引的不同TProc的容器。就像TDictionary一样。
TMessageBus = class
private
fContainer: TDictionary<String, TProc<T>>; // ERROR !!
public
procedure Send<T>(aName: String; aData: T); // producer
procedure Subscribe<T>(aName: String; aProc: TProc<T>); // consumer
end;请帮帮忙。
发布于 2019-09-16 23:09:08
知道TProc<T>是作为接口实现的,您可以编写以下代码:
type
TMessageBus = class
private
fContainer: TDictionary<string, IInterface>;
public
constructor Create;
destructor Destroy; override;
procedure Send<T>(const aName: string; const aData: T);
procedure Subscribe<T>(const aName: string; const aProc: TProc<T>);
end;
constructor TMessageBus.Create;
begin
fContainer := TDictionary<string, IInterface>.Create;
end;
destructor TMessageBus.Destroy;
begin
fContainer.Free;
inherited;
end;
procedure TMessageBus.Send<T>(const aName: string; const aData: T);
begin
TProc<T>(fContainer[aName])(aData);
end;
procedure TMessageBus.Subscribe<T>(const aName: string; const aProc: TProc<T>);
begin
fContainer.AddOrSetValue(aName, IInterface(PPointer(@aProc)^));
end;但是,除了省略任何验证代码之外,如果您发送的数据类型与订阅的数据类型不同,这很容易失败。因此,我将在这里使用TValue类型将传递的TProc<T>包装在TProc<TValue>中(来自System.Rtti)。但是请记住,TValue本身只允许编译器允许的类型转换,所以它不会将string转换为Integer或类似的类型-但如果需要,您可以自己添加以下内容:
type
TMessageBus = class
private
fContainer: TDictionary<string, TProc<TValue>>;
public
constructor Create;
destructor Destroy; override;
procedure Send<T>(const aName: string; const aData: T);
procedure Subscribe<T>(const aName: string; const aProc: TProc<T>);
end;
constructor TMessageBus.Create;
begin
fContainer := TDictionary<string, TProc<TValue>>.Create;
end;
destructor TMessageBus.Destroy;
begin
fContainer.Free;
inherited;
end;
procedure TMessageBus.Send<T>(const aName: string; const aData: T);
var
proc: TProc<TValue>;
begin
if fContainer.TryGetValue(aName, proc) then
proc(TValue.From<T>(aData));
end;
procedure TMessageBus.Subscribe<T>(const aName: string; const aProc: TProc<T>);
begin
fContainer.AddOrSetValue(aName,
procedure(aValue: TValue)
begin
aProc(aValue.AsType<T>);
end);
end;例如,如果您现在调用mb.Send('somestring', 42);,它将在TValue.AsType中引发EInvalidCast异常,因为如前所述,它不能将传递的42转换为string,这是您在调用Subscribe时指定的。
发布于 2019-09-16 20:10:25
如果您有一个依赖于泛型类型T的字段,则必须使完整的类成为泛型,而不是方法:
type
TMessageBus<T> = class
private
fContainer: TDictionary<String, TProc<T>>; // ERROR !!
public
procedure Send(aName: String; aData: T); // producer
procedure Subscribe(aName: String; aProc: TProc<T>); // consumer
end;https://stackoverflow.com/questions/57955941
复制相似问题