2014-08-28 2 views
5

Ich verwende Request/Response-Muster auf einer Service-Schicht. Ich habe zum Beispiel:Antwort-/Anfrage-Muster ... Wie gestalten Sie die DTOs?

public class FindPostsByTypeRequest : Request { 
    public PostType Type { get; set; } 
} 

public class FindPostsByTypeResponse : Response { 
    public IList<PostDto> Posts { get; set; } 

    public class PostDto { 
    public Int32 Id { get; set; } 
    public String Title { get; set; } 
    public String Text { get; set; } 
    } 
} 

Um diese Anfrage zu behandeln Ich habe einen Handler:

public class FindPostsByTypeHandler : Handler<FindPostsByTypeRequest, FindPostsByTypeResponse> { 

    private IContext _context; 

    public FindPostsByTypeHandler(IContext context) { 
    _context = context; 
    } 

    public FindPostsByTypeResponse Handle(FindPostsByTypeRequest request) { 

    IList<FindPostsByTypeRequest.PostDto> posts = _context.Posts 
    .Where(x => x.Type == request.Type) 
    .Select(x => new FindPostsByTypeRequest.PostDto { 
     Id = x.Id, 
     Title = x.Title, 
     Text = x.Text 
    }).ToList(); 

    return new FindPostsByTypeResponse { Posts = posts }; 

    } 

} 

Dann habe ich einen Dispatcher und verwenden Sie es wie folgt:

FindPostsByTypeRequest request = new FindPostsByTypeRequest { Type = type }; 

FindPostsByTypeResponse response = _dispatcher.Send<FindPostsByTypeResponse>(request); 

Das Problem Ich versuche zu lösen:

Wenn ich nach Posts nach Typ s suchen Manchmal brauche ich die Tags ... Manchmal nicht. Natürlich konnte ich immer die Tags in meine DTOs bekommen und es verwenden oder nicht ... Aber etwas Laden, den ich vermeiden ...

Also nicht benötigen, sollten

im Grunde muss ich die Beiträge von Typ erhalten und "Sagen" Sie dem Handler, welche Daten ich brauche.

_dispatcher.Send<FindPostsByTypeResponse<PostWithTagsModel>>(request); 

Wo PostWithTagsModel die DTO ich brauchen würde wäre:

würde meine Idee, etwas Ähnliches sein. Da ist in meinem Handler hätte ich:

public class FindPostsByTypeHandler : Handler<FindPostsByTypeRequest, FindPostsByTypeResponse> { 

    private IContext _context; 

    public FindPostsByTypeHandler(IContext context) { 
    _context = context; 
    } 

    public FindPostsByTypeResponse<PostsByType> Handle(FindPostsByTypeRequest request) { 

    IList<FindPostsByTypeResponse.PostDto> posts = _context.Posts 
    .Where(x => x.Type == request.Type) 
    .Select(x => new FindPostsByTypeResponse.PostDto { 
     Id = x.Id, 
     Title = x.Title, 
     Text = x.Text 
    }).ToList(); 

    return new FindPostsByTypeResponse { Posts = posts }; 

    } 

    public FindPostsByTypeResponse<PostsWithoutTagsDto> Handle(FindPostsByTypeRequest request) { 

    IList<FindPostsByTypeResponse.PostsWithoutTagsDto> posts = _context.Posts 
    .Where(x => x.Type == request.Type) 
    .Select(x => new FindPostsByTypeResponse.PostsWithoutTagsDto { 
     Id = x.Id, 
     Title = x.Title, 
     Text = x.Text 
    }).ToList(); 

    return new FindPostsByTypeResponse { Posts = posts }; 

    } 

    public FindPostsByTypeResponse<PostsWithTagsDto> Handle(FindPostsByTypeRequest request) { 
    // Remaining code 
    } 

} 

Ich bin nicht sicher, dies ist möglich oder sogar der beste Weg, dies zu tun ...

Grundsätzlich muß ich „sagen,“ der Handler, in welchem ​​Format I brauche die DTOs, die in der Antwort enthalten sind.

Wie kann oder soll ich das tun?

Antwort

0

AKTUALISIERT:

Ok, ohne genau zu wissen, was Sie anderen Klassen aussehen, hier ist ein ungefähres Beispiel dafür, was ich denke, für Sie enthalten alle Nebenklassen funktionieren würde. Ich habe dies in Visual Studio zusammengefügt und bestätigt, dass es kompiliert wird. Bei diesem Ansatz bestimmen die Unterklasseninstanzen ResponseTypeEnum anhand der Typzuordnung über die ConstructItem-Methode für die untergeordnete Enum-Klasse, welche Art von Post instanziiert werden soll.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace TestRequestResponse 
{ 

    #region Generic portions 

    /// <summary> 
    /// Base request class 
    /// </summary> 
    public class  Request {} 

    /// <summary> 
    /// Base response class 
    /// </summary> 
    public class  Response {} 

    /// <summary> 
    /// Generic typed namespace for Response/Request support 
    /// </summary> 
    /// <typeparam name="tRequestResponseSet">Request/Response set type parameter (for namespace constraining)</typeparam> 
    /// <typeparam name="tItem">Item type parameter</typeparam> 
    /// <typeparam name="tSourceItem">Source item type parameter</typeparam> 
    public class  RequestResponseSet<tRequestResponseSet, tItem, tSourceItem> 
      where  tRequestResponseSet : RequestResponseSet<tRequestResponseSet, tItem, tSourceItem> 
      where  tItem    : RequestResponseSet<tRequestResponseSet, tItem, tSourceItem>.Item 
    { 

     /// <summary> 
     /// Base item class 
     /// </summary> 
     public 
     abstract class Item 
     { 
      public 
      abstract void Initialize(tSourceItem sourceItem); 
     } 

     /// <summary> 
     /// Base type specific subclassable enum class (see https://github.com/TyreeJackson/atomic/blob/master/Atomic.Net/DataTypes/SubclassableEnum.cs for a more generic version) 
     /// </summary> 
     public 
     abstract class ResponseTypeEnum 
     { 
      private 
      static  Dictionary 
         < 
          string, 
          ResponseTypeEnum 
         >      allValues      = new Dictionary<string,ResponseTypeEnum>(); 
      private  string     type; 
      private  Func<tItem>    constructItem; 
      protected       ResponseTypeEnum 
               (
                string  type, 
                Func<tItem> constructItem 
               ) 
      { 
       this.type   = type; 
       this.constructItem = constructItem; 
      } 

      public  tItem     ConstructItem(tSourceItem sourceItem) 
      { 
       var returnItem = this.constructItem(); 
       returnItem.Initialize(sourceItem); 
       return returnItem; 
      } 

      public 
      static  ResponseTypeEnum  Select(string type) 
      { 
       ResponseTypeEnum returnTypeEnum = null; 
       return type == null || !ResponseTypeEnum.allValues.TryGetValue(type, out returnTypeEnum) 
         ? null 
         : returnTypeEnum; 
      } 

      public 
      static 
      implicit 
      operator       ResponseTypeEnum(string type) 
      { 
       return ResponseTypeEnum.Select(type); 
      } 

      public 
      static 
      implicit 
      operator       string(ResponseTypeEnum typeEnum) 
      { 
       return typeEnum == null ? null : typeEnum.type; 
      } 

     } 

    } 

    #endregion Generic portions 

    #region Post specific portions 

    /// <summary> 
    /// Stored post /entity 
    /// </summary> 
    public class  StoredPost 
    { 
     public String   Type { get; set; } 
     public Int32   Id  { get; set; } 
     public String   Title { get; set; } 
     public String   Text { get; set; } 
     public List<String> Tags { get; set; } 
    } 

    /// <summary> 
    /// Post specific typed namespace 
    /// </summary> 
    public class  PostsSet : RequestResponseSet<PostsSet, PostsSet.Post, StoredPost> 
    { 

     public class Types : ResponseTypeEnum 
     { 

      public static  Types Basic  = new Types("basic", ()=>new Post()); 
      public static  Types WithTags = new Types("withTags",()=>new PostWithTags()); 

      protected     Types(string type, Func<Post> createPost) : base(type, createPost) {} 
     } 

     public class Post : Item 
     { 
      public  Int32 Id  { get; set; } 
      public  String Title { get; set; } 
      public  String Text { get; set; } 

      public 
      override void Initialize(StoredPost sourceItem) 
      { 
       this.Id  = sourceItem.Id; 
       this.Title = sourceItem.Title; 
       this.Text = sourceItem.Text; 
      } 

     } 

     public class PostWithTags : Post 
     { 
      public  List<String> Tags { get; set; } 

      public 
      override void   Initialize(StoredPost sourceItem) 
      { 
       base.Initialize(sourceItem); 
       this.Tags = sourceItem.Tags; 
      } 
     } 

    } 

    /// <summary> 
    /// Post specific response class 
    /// </summary> 
    public class  FindPostsResponse : Response 
    { 
     public IList<PostsSet.Post> Posts { get; set; } 
    } 

    /// <summary> 
    /// Post specific request class 
    /// </summary> 
    public class  FindPostsRequest : Request 
    { 
     public string Type { get; set; } 
    } 

    /// <summary> 
    /// Post specific context 
    /// </summary> 
    public interface IContext 
    { 
     IEnumerable<StoredPost> Posts { get; set; } 
    } 

    /// <summary> 
    /// Post specific handler 
    /// </summary> 
    public class  FindPostHandler 
    { 

     private IContext   context; 

     public      FindPostHandler(IContext context) 
     { 
      this.context = context; 
     } 

     public FindPostsResponse Handle(FindPostsRequest request) 
     { 
      var type = PostsSet.Types.Select(request.Type); 

      return 
      type == null 
      ? null 
      : new FindPostsResponse() 
       { 
        Posts = 
        this.context.Posts 
        .Where(x => x.Type == request.Type) 
        .Select(x => type.ConstructItem(x)) 
        .ToList() 
       }; 
     } 

    } 

    #endregion Post specific portions 

} 
+0

Nicht wirklich. Ich brauche etwas allgemeineres und ich muss in die Anfrage eingehen, welchen Typ ich will. Wie würdest du den Dispatcher an deinem Beispiel benutzen? –

+7

Seitennotiz ... Ich habe noch nie so eine verrückte Formatierung gesehen – AlexFoxGill

+0

Die Formatierung ist nützlich, wenn man die Methoden betrachtet, wenn sie mit ctrl M-O kollabiert sind. Die Idee ist, eine Methode auf einmal statt mehrerer gleichzeitig zu betrachten. Grundsätzlich ist der erste Tabstop die Modifikatorspalte, der zweite ist die Typ-/Rückgabetypspalte, der dritte ist der Name der Eigenschaft/des Feldes/der Methode, und der vierte optionale ist die Feldinitialisierung oder property {get; einstellen;}. –

Verwandte Themen