字符串到模板类型通过Object.factory(...)

时间:2016-10-18 06:12:47

标签: d

可以将字符串转换为模板参数,或者,是否有一种惯用的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
{
    // ....
}

1 个答案:

答案 0 :(得分:1)

您不能将运行时值用作模板参数。但你有选择:

  1. 将其强制转换为IEvent,并让事件以重载函数启动apply。 (Visitor pattern

    class UserCreated : IEvent
    {   
        override void apply(Aggregate aggregate){
            aggregate.apply(this);
        }
    }
    
  2. 使用运行时类型信息相应地调度事件。

    void dispatch(Object event){
        if(auto casted = cast(UserCreated)event){
            apply(casted);
        }
        // ...
    }