2014-05-17 21 views
5

İstemcinin sunucuya farklı komut türleri gönderebileceği ve belirli sonuçları alabileceği basit istemci-sunucu çözümü üzerinde çalışıyorum. Komutların farklı özellikleri olabilir. Sahip olmak istediğim, ele aldığı komutun türüne göre belirli bir komut işleyicisinin seçilebileceği bir mimaridir.Dökümünüzü daha iyi bir desenle değiştirin

public interface ICommand 
{ 
} 

public class CommandA: ICommand 
{ 
    public string CustomProperty { get; set; } 
} 

public class CommandB: ICommand 
{ 
} 

Her komut komutu işleme ve sonucu dönen sorumludur kendi CommandHandler vardır: şöyle temel altyapıyı oluşturdu.

public interface ICommandHandler 
{ 
    bool CanHandle(ICommand command); 
    IReply Handle(ICommand command); 
} 

public abstract class CommandHandlerBase<TCommand> : ICommandHandler 
    where TCommand : class, ICommand 
{ 
    public bool CanHandle(ICommand command) 
    { 
     return command is TCommand; 
    } 

    public IReply Handle(ICommand command) 
    { 
     return Handle(command as TCommand); 
    } 

    public abstract IReply Handle(TCommand command); 
} 

// Specific handler 
public class CommandAHandler : CommandHandlerBase<CommandA> 
{ 
    public override IReply Handle(CommandA command) 
    { 
     //handling command and returning result 
     return null; 
    } 
} 

Ben de sonucu uygun işleyicisi seçme ve dönen sorumlu bir sınıf yarattı: Hepsi CommandHandlerBaseClass devralan Ben CommandHandlerBase sınıfta döküm sevmiyorum

public interface IReplyCreator 
{ 
    IReply GetReply(ICommand command); 
} 

public class ReplyCreator : IReplyCreator 
{ 
    private readonly IEnumerable<ICommandHandler> _commandHandlers; 

    public ReplyCreator(IEnumerable<ICommandHandler> commandHandlers) 
    { 
     _commandHandlers = commandHandlers; 
    } 

    public IReply GetReply(ICommand command) 
    { 
     var commandHandler = _commandHandlers 
      .FirstOrDefault(x => x.CanHandle(command)); 

     if (commandHandler == null) 
      return null; 
     return commandHandler.Handle(command); 
    } 
} 

ama bulamıyorum Bunu önlemek için herhangi bir desen. Aşağıda gösterildiği gibi genel bir arayüz oluşturabilirim, ancak ReplyCreator'da belirli bir işleyiciyi nasıl kaydedip seçebilirim? şöyle sunucusunda alınan

public interface ICommandHandler<TCommand> 
    where TCommand : ICommand 
{ 
    bool CanHandle(TCommand command); 
    IReply Handle(TCommand command); 
} 

komutları Json.NET ile serileştirildiğini:

JsonConvert.SerializeObject(new CommandA(), new JsonSerializerSettings 
    { 
     TypeNameHandling = TypeNameHandling.All 
    };) 

Yani sonuçta somut komuta içine serileştirilemezse ve uygun işleyici tarafından ele alınması gereken bir dize alır. Böyle bir senaryoda oyunculardan kaçmanın bir yolu var mı? StructureMap'i IoC kitaplığım olarak kullanıyorum.

cevap

3

Neden bu yayınlardan kaçınmaya çalışıyorsunuz? Şimdi aklıma gelen herhangi bir geçici çözüm bundan daha hoş olmayacaktır.

Bu amaçla as anahtar sözcüğünü kullanmaktan kaçınıyorum. İşleyiciye yanlış tip geçtiğinde, olası bir durumda sessizce başarısız olur. Böyle durumlarda, kodunuzun içinde bir yere değil, hemen atılmasına istisna olmasını istersiniz.

+2

Anlaşmalı. Kolu (TCommand olarak komut) 'yerine 'Sap ((TCommand) komutu)' yazmalıdır. – Timwi

+0

@SoftwareFactor Döküm ile kesinlikle yaşayabilirim, ancak yakın geçmişte birkaç kez benzer bir desen kullandığımı ve başka bir şeyle değiştirilebileceğini merak ettim, belki daha iyi. Ve sen harikasın, bu durumda 'olarak' kullanmamalıyım. –