可以将字符串转换为模板参数,或者,是否有一种惯用的D方法来实现将反序列化的类作为类/函数模板参数传递的概念。
该概念基于DDD, CQRS and Eventsourcing。
import std.stdio;
void main()
{
auto aggregate = new UserAggregate();
auto command = new CreateUser();
// in a command bus, aggregates are loaded based on the aggregate type, then commands and events are applied.
aggregate.handle(command);
// NOTE typecast cannot be used as events will be loaded from an event stream and deserialized - only the
// class name (fully qualified module path) is known at runtime.
auto userCreated = Object.factory("app.UserCreated");
// .... deserialization of event ....
aggregate.apply(userCreated); // <-- compile error - type not specific enough and casting is not possible
}
// interfaces
interface IHandleCommand(TCommand : ICommand)
{
void handle(TCommand command);
}
interface IApplyEvent(TEvent : IEvent)
{
void apply(TEvent event);
}
interface ICommand
{
// ....
}
interface IEvent
{
// ....
}
// Implementation
class UserAggregate :
IHandleCommand!CreateUser,
IHandleCommand!ChangeUserStatus,
IApplyEvent!UserCreated,
IApplyEvent!UserStatusChanged
{
void handle(CreateUser createUser)
{
writeln("createUser...");
}
void handle(ChangeUserStatus changeUserStatus)
{
writeln("changeUserStatus...");
}
void apply(UserCreated userCreated)
{
writeln("userCreated...");
}
void apply(UserStatusChanged userStatusChanged)
{
writeln("userStatusChange...");
}
}
// Commands
class CreateUser : ICommand
{
// ....
}
class ChangeUserStatus : ICommand
{
// ....
}
// Events
class UserCreated : IEvent
{
// ....
}
class UserStatusChanged : IEvent
{
// ....
}
答案 0 :(得分:1)
您不能将运行时值用作模板参数。但你有选择:
将其强制转换为IEvent,并让事件以重载函数启动apply
。 (Visitor pattern)
class UserCreated : IEvent
{
override void apply(Aggregate aggregate){
aggregate.apply(this);
}
}
使用运行时类型信息相应地调度事件。
void dispatch(Object event){
if(auto casted = cast(UserCreated)event){
apply(casted);
}
// ...
}