2016-10-18 6 views
0

文字列をテンプレートパラメータに変換できます。あるいは、逆シリアル化されたクラスをクラス/関数テンプレートのパラメータとして渡すという概念を達成するための慣用的な方法です。Object.factory(...)を介した文字列型への文字列

概念は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

使用してください[ショート、自炊、(コンパイル可能)正しい、例】(http://sscce.org/)■。誰もあなたが持っているインターフェースの数を気にせず、実際の問題から気をそらす。 – weltensturm

+0

'void apply(UserCreated userCreated)'を 'void apply(IEvent userCreated)'に変更しようとしましたか? – DejanLekic

+0

@DejanLekic 1つのインタフェースタイプのみを使用して集約でイベントを識別する場合、どのように異なるイベントタイプを扱うでしょうか? – MX4399

答えて

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); 
        } 
        // ... 
    } 
    
+0

#1すべてのIEventインスタンスに適用メソッドを実装して、間接的に集約タイプをバインドしていることを暗示しますか?命令バスの実装には知られていない型が導入されるので、#2直接型変換は不可能です。 #2は[string mixins](https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/D-templates-tutorial.md#string-mixins)で処理できます – MX4399

+0

#1はい、#2 mixinはCTE文字列でしか動作しないため、コンパイル時に扱う必要があるすべての型をUserAggregateに知らせる必要があります。しかし、型リストは文字列より優れています。あなたの質問は、とにかく未知の型を扱う方法を示していない、UserAggregateはそれらのすべてを知っているようだ。 – weltensturm

+1

#2 btwの場合は、キャストを行い、nullをチェックすることができます: 'if(auto casted = cast(UserCreated)event)apply(casted);'これは少し良いです。 –

関連する問題