2013-06-18 9 views
5

मैं अब थोड़ी देर में विंडसर कैसल का उपयोग करता हूं। यह उन वातावरणों के लिए बिल्कुल सही है जहां डेटा डेटाबेस या जैसे में स्थित है, जहां रिपोजिटरी पैटर्न या यूनिटोफवर्क पैटर्न अच्छी तरह से काम करता है।विंडसर कैसल/डीआई और ऑब्जेक्ट मॉडल

अब मेरे पास एक अलग स्थिति है: मेरे पास एक जटिल ऑब्जेक्ट मॉडल है जो कई एकल पीओएनओ द्वारा इकट्ठा किया जाता है। पर्यावरण को अधिक स्पष्ट बनाने के लिए COM द्वारा दृढ़ता से प्रभावित किया जाता है: एक्सेल, वर्ड पीआईओ का भारी उपयोग किया जाता है।

मैं कमांड पैटर्न का उपयोग करता हूं, मैंने आईसीओएमएंड हैंडलर को here वर्णित किया लेकिन एक अंतर के साथ लागू किया। जैसा कि मैं कमांड कमांड पैटर्न के बगल में कुछ भी जानने के बिना रन में कॉल करने के लिए आदेशों की सूची में असेंबली कमांड करना चाहता हूं, यह निष्पादन विधि को कॉल करते समय संदर्भ को प्रस्तुत नहीं करता है। तो इंटरफ़ेस इस तरह दिखता है:

public interface ICommand 
    { 
     void Execute(); 
     bool CanExecute(); 
    } 

उस इंटरफ़ेस के साथ कमांड का निष्पादन प्रभावी और समझने में आसान है। दूसरी ओर यह सीटीओआर के साथ संदर्भ पेश करने में एक समस्या है क्योंकि इसलिए कंटेनर को स्पष्ट रूप से उदाहरण के लिए बुलाया जाना चाहिए। सीटीआर पैरामीटर जोड़ें।

इसलिए मैं वास्तव में दो प्रश्न हैं:

  1. इसकी सुई एक संभव है - कंटेनर explictely बुला बिना विंडसर कैसल द्वारा स्वचालित रूप से - चलो यह एक संदर्भ, ऑब्जेक्ट मॉडल का एक हिस्सा कहते हैं?
  2. DI का उपयोग कर कमांड पैटर्न से कैसे भाग लें? here वर्णित आरआरआर नियम का पालन करके कार्यों/कार्यों की सूची को परिभाषित करने में सक्षम होने के बारे में कोई विचार कैसे पूरा किया जा सकता है?
+0

आप कमांड/हैंडलर पैटर्न का एक विवरण ('ICommandHandler ' का प्रयोग करके) से लिंक, लेकिन वास्तव में आप कमान पैटर्न है, जो पूरी तरह से अलग है, क्योंकि आदेश/हैंडलर पैटर्न में आदेशों व्यवहार के बिना DTOs हैं प्रयोग कर रहे हैं, और उनमें कोई 'निष्पादन विधि' नहीं है। उन पर 'निष्पादन' विधि होने से कमांड/हैंडलर पैटर्न लाए जाने वाले अधिकांश क्षमताओं को अक्षम करता है। जब आप हैंडलरों में निर्भरता इंजेक्ट करते हैं तो आदेशों में इंजेक्शन निर्भरताओं के साथ समस्याएं समाप्त हो जाएंगी। कमांड/हैंडलर पैटर्न में, कमांड की कोई निर्भरता नहीं होती है (क्योंकि उनके पास कोई व्यवहार नहीं है)। – Steven

+0

उत्तर के लिए धन्यवाद, स्टीवन। आप निश्चित रूप से सही हैं, मैं उन्हें हैंडलर में इंजेक्ट कर सकता हूं। लेकिन इससे समस्या हल नहीं होती है, क्योंकि मुझे अभी भी एक ही जानकारी इंजेक्ट करना है और हैंडलर को अपना डेटा उपलब्ध कराने के लिए कंटेनर को कॉल करना है। आदेशों को बैच करना और उन्हें एक पंक्ति में निष्पादित करना संभव नहीं होगा। क्या मुझे कुछ गलत मिला? –

उत्तर

4

इन्फ्रास्ट्रक्चर:

public interface ICommandHandler<in T> 
{ 
    void Handle(T command); 
} 

public interface ICommandExecutor 
{ 
    CommandResult ExecuteCommand(Command command); 
    CommandResult ExecuteCommands(Command[] commands); 
} 

public abstract class Command 
{ 

} 

public class CommandExecutor : ICommandExecutor 
{ 
    private readonly IWindsorContainer _kernel; 

    public CommandExecutor(IWindsorContainer kernel) 
    { 
     Guard.AssertNotNull(() => kernel); 
     _kernel = kernel; 
    } 

    public CommandResult ExecuteCommand(Command command) 
    { 
     return ExecuteInternal(command); 
    } 

    public CommandResult ExecuteCommands(Command[] commands) 
    { 
     CommandResult result = null; 

     foreach (Command command in commands) 
     { 
      result = ExecuteInternal(command); 

      if (!result.IsExecuted) 
       return result; 
     } 

     return result ?? CommandResult.Executed("Command executed successfully"); 
    } 

    private CommandResult ExecuteInternal(Command command) 
    { 
     dynamic handler = FindHandlerForCommand(command); 

     try 
     { 
      handler.Handle(command as dynamic); 
      return CommandResult.Executed("Command executed successfully"); 
     } 
     finally 
     { 
      _kernel.Release(handler); 
     } 
    } 

    private object FindHandlerForCommand(Command command) 
    { 
     Type handlerType = typeof (ICommandHandler<>).MakeGenericType(command.GetType()); 
     dynamic handler = _kernel.Resolve(handlerType); 
     return handler; 
    } 
} 

पंजीकरण:

 container.Register(Component.For<ICommandExecutor>().ImplementedBy<CommandExecutor>() 
      .Interceptors<ExceptionToCommandResult>() 
      .Interceptors<ExceptionLogger>() 
      .Interceptors<HandleWhenDeadlockVictim>() 
      .Interceptors<RetryCommand>() 
      .Interceptors<ContainerScopeWrapper>() 
      .Interceptors<TransactionWrapper>() 
      .Interceptors<SameNhibernateSessionAndTransactionWrapper>()); 

उदाहरण:

public class WriteComment : Command 
{ 
    public string GameToCommentId { get; set; } 

    public string Comment { get; set; } 
} 

public class WriteCommentCommandHandler : ICommandHandler<WriteComment> 
{ 
    private readonly IGameRepository _repository; 

    public WriteCommentCommandHandler(IGameRepository repository) 
    { 
     Guard.AssertNotNull(() => repository); 
     _repository = repository; 
    } 

    public void Handle(WriteComment command) 
    { 
     var game = _repository.Get(new Guid(command.GameToCommentId)); 

     game.WriteComment(command.Comment, DateTime.Now); 
    } 
} 

सब AOP सामान लेनदेन संभालती है और इसके आगे। आदेश निष्पादक एक स्टेटलेस सिंगलटन है, हैंडलर अपनी अलग-अलग ज़रूरतों को निर्दिष्ट करते हैं। कमांड निष्पादक सिर्फ बुनियादी ढांचे और डोमेन-अज्ञेयवादी है, इसलिए इसे अपने डोमेन से बाहर रखें जहां इसे रखें। यह एक बड़ी प्रणाली पर उत्पादन कोड है, एक आकर्षण की तरह काम करता है।

+0

मारियस, बहुत धन्यवाद। बहुत व्यापक इसकी एक बार कोशिश करूंगा! –

संबंधित मुद्दे