5

के लिए सरल इंजेक्टर उपयोग Simpleinjector विकी में निर्देशों के अनुसार इंटरफेस, कमांड और कमांड हैंडलर सेट अप।जेनेरिक कमांड हैंडलर

public interface ICommand 
{ 
    string Name { get; set; } 
} 

public class Command1 : ICommand 
{ 
    public string Name { get; set; } 
} 

public class Command2 : ICommand 
{ 
    public string Name { get; set; } 
} 

public interface ICommandHandler<TCommand> 
{ 
    void Execute(TCommand Command); 
} 

public class Command1Handler : ICommandHandler<Command1> 
{ 
    public void Execute(Command1 Command) { 
     Console.WriteLine(Command.Name); 
    } 
} 

public class Command2Handler : ICommandHandler<Command2> 
{ 
    public void Execute(Command2 Command) { 
     Console.WriteLine(Command.Name + "Hello"); 
    } 
} 

डेकोरेटर:

public class CommandDecorator<TCommand> : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> _handler; 

    public CommandDecorator(ICommandHandler<TCommand> handler) 
    { 
     this._handler = handler; 
    } 

    public void Execute(TCommand command) 
    { 
     this._handler.Execute(command); 
    } 
} 

नमूना कार्यक्रम

public class Program 
{ 
    static void Main(string[] args) 
    { 
     Container container = new Container(); 

     //registering 
     container.RegisterAll<ICommand>(typeof(Command1), typeof(Command2)); 

     container.RegisterManyForOpenGeneric(
      typeof(ICommandHandler<>), 
      typeof(ICommandHandler<>).Assembly); 

     container.RegisterDecorator(typeof(ICommandHandler<>), 
      typeof(CommandDecorator<>)); 

     container.Verify(); 

     // sample test command 
     ICommand testcommand = new Command2(); 
     testcommand.Name = "command 1"; 

     var type = typeof(ICommandHandler<>).MakeGenericType(testcommand.GetType()); 

     dynamic instance = container.GetInstance(type); 
     instance.Execute((dynamic)testcommand); 
    } 
} 

इस सही तरीके से रन टाइम पर आदेश से निपटने के लिए सही हैंडलर प्राप्त करने के लिए है। यह एक नमूना है और वास्तविक ऐप में कमांड कतार में पोस्ट करने जा रहे हैं और एक सेवा कमांड पढ़ने और इसे संसाधित करने जा रही है। मुझे लगता है कि सजावटी के लिए इसका उपयोग किया जाना चाहिए लेकिन मैं इसे काम करने में सक्षम नहीं हूं। यदि कोई हो तो बेहतर विकल्प सुझाएं।

उत्तर

5

आपके आदेश (Command1 और Command2) सेवाएं नहीं हैं: उन्हें पंजीकृत नहीं होना चाहिए। वे रनटाइम डेटा (संदेश) हैं जिन्हें आप अपनी सेवाओं (आपके कमांड हैंडलर) से गुजरते हैं। तो आपको RegisterAll<ICommand> पंजीकरण को हटा देना चाहिए। इसका कोई उपयोग नहीं है। आप पहले से ही इसका उपयोग नहीं देख रहे हैं, क्योंकि आपके उदाहरण में आप Command2 मैन्युअल रूप से नए हैं, जो करना सही है।

कोड की आखिरी तीन पंक्तियों में आप क्या कर रहे हैं, किसी अज्ञात प्रकार के आदेश को दाएं कमांड हैंडलर पंजीकरण में प्रेषित कर रहा है। इसे हमेशा खींचने के लिए आपको कुछ प्रतिबिंब की आवश्यकता है, क्योंकि आपको आदेश प्रकार के आधार पर बंद ICommandHandler<TCommand> प्रकार बनाने की आवश्यकता है, जो कुछ ऐसा है जिसे आप संकलित समय पर नहीं जानते हैं। सी # dynamic कीवर्ड का उपयोग करने के बजाय, आप .NET प्रतिबिंब API का भी उपयोग कर सकते हैं, लेकिन dynamic का उपयोग करके मेरे अनुभव में इस विशेष मामले में बेहतर है। प्रतिबिंब एपीआई का एक महत्वपूर्ण नकारात्मक पक्ष यह है कि एपीआई हमेशा InvocationException के साथ किसी भी फेंक दिया अपवाद (विफलता के मामले में) लपेटेगा और इससे कॉल स्टैक को संभालने में कुछ अपवाद करना मुश्किल हो जाता है।

इतने लंबे समय कहानी संक्षेप में, यह आपके पंजीकरण होना चाहिए:

Container container = new Container(); 

    container.RegisterManyForOpenGeneric(
     typeof(ICommandHandler<>), 
     typeof(ICommandHandler<>).Assembly); 

    container.RegisterDecorator(typeof(ICommandHandler<>), 
     typeof(CommandDecorator<>)); 

और यह भेजने तर्क होना चाहिए:

var type = typeof(ICommandHandler<>).MakeGenericType(command.GetType()); 

    dynamic handler = container.GetInstance(type); 
    handler.Execute((dynamic)command); 
संबंधित मुद्दे