2009-03-18 12 views
14

मैं किसी दिए गए विंडसर-कंटेनर में एक (डिफ़ॉल्ट) कार्यान्वयन को फिर से परिभाषित करना चाहता हूं। क्या ओवरव्राइट क्या है? हालांकि काम नहीं करता है।महल विंडसर के साथ एक घटक को ओवरराइट कैसे करें?

container.Register(
        Component.For<IServiceOperationAuthorization>() 
          .OverWrite() 
          .Instance(_authorization) 
        ); 

कोई अन्य विचार?

चियर्स, लार्स

उत्तर

1

जहाँ मैं ओवरराइड के लिए एक्सएमएल-फ़ाइलें गठबंधन और चूक के लिए धाराप्रवाह पंजीकरण का उपयोग मैं वास्तव में एक अच्छा समाधान नहीं मिला।

धाराप्रवाह-एपीआई एक प्रकृति का पूर्ण नाम डिफ़ॉल्ट कुंजी के रूप में लेता है। फ्लाई पर मैं धाराप्रवाह-एपीआई के प्रमुख-सम्मेलनों की नकल करने के लिए आईडीएमएल-कॉन्फ़िगर की आईडी को ओवरराइड करता हूं।

तब मैं एक्सएमएल-config रजिस्टर, जबकि मैं Kernel.ComponentRegistered को सुनने के।

बाद में मैं केवल कोड-कॉन्फ़िगरेशन से सेवाएं जोड़ता हूं जहां xml ने अभी तक सेवा को परिभाषित नहीं किया है।

(यह कुछ समय पहले है और मैं बस कोड को कॉपी-पेस्ट किया। उम्मीद है कि आप यह काम कर रहा। मैं संपादन कर देंगे यदि आपको कोई समस्या मिलती प्राप्त)

IList<Type> unnamedServices = new List<Type>(); 
IDictionary<string, Type> namedServices = new Dictionary<string, Type>(); 

ComponentDataDelegate registered = captureRegistrations(unnamedServices, namedServices); 

container.Kernel.ComponentRegistered += registered; 

// The method that captures the services 
private static ComponentDataDelegate captureRegistrations(
    IList<Type> unnamedServices, IDictionary<string, Type> namedServices) 
{ 
     return (key, handler) => 
       { 
        if (handler.ComponentModel.Name == handler.ComponentModel.Implementation.FullName) 
        { 
         unnamedServices.Add(handler.Service); 
        } 
        else 
        { 
         namedServices.Add(key, handler.Service); 
        } 
       }; 
} 

उसके बाद इससे पहले कि मैं सेवाओं रजिस्टर कोड में, मैं जांचता हूं कि वे पहले ही पंजीकृत हैं या नहीं। मैंने एक बेस क्लास भी बनाया जो इसे और अधिक आसान बनाता है।

public class ApplicationConfiguration : WindsorConfigurationSkeleton 
{ 
    internal static WindsorServiceLocator create() 
    { 
     var container = createWith(null, "components-config.xml", coreServices, caches, roles); 
     return new WindsorServiceLocator(container); 
    } 

    internal static IEnumerable<IRegistration> coreServices() 
    { 
     yield return Component.For<ISystemClock>() 
      .ImplementedBy<PreciseSystemClock>() 
      .Parameters(Parameter.ForKey("synchronizePeriodSeconds").Eq("10")) 
      .LifeStyle.Singleton; 

     yield return Component.For<IMailService>() 
      .ImplementedBy<MailQueueService>() 
      .LifeStyle.Singleton; 
    } 

    internal static IEnumerable<IRegistration> caches() 
    { 
     yield return Component.For<IDataCache<ServiceAttributes>>() 
      .ImplementedBy<NoDataCache<ServiceAttributes>>() 
      .LifeStyle.Singleton; 

     // .... 
    } 
} 

आधार वर्ग कि तारों करता है:: (लॉगिंग Commons.Logging से है)

public class WindsorConfigurationSkeleton 
{ 
    private static readonly ILog _log = LogManager.GetLogger(
     typeof(WindsorConfigurationSkeleton)); 

    internal static IWindsorContainer createWith(
     IRegistration[] customs, string configFile, params Func<IEnumerable<IRegistration>>[] methods) 
    { 
     IWindsorContainer container = new WindsorContainer(); 
     BugFix.Kernel = container.Kernel; 

     container.AddFacility("factory.support", new FactorySupportFacility()); 

     IList<Type> unnamedServices = new List<Type>(); 
     IDictionary<string, Type> namedServices = new Dictionary<string, Type>(); 

     ComponentDataDelegate registered = captureRegistrations(unnamedServices, namedServices); 

     container.Kernel.ComponentRegistered += registered; 

     if (customs != null) 
     { 
      container.Register(customs); 
     } 

     if (configFile != null) 
     { 
      tryAddXmlConfig(container, configFile); 
     } 

     container.Kernel.ComponentRegistered -= registered; 

     if (methods != null && methods.Length > 0) 
     { 
      container.Register(union(unnamedServices, namedServices, methods)); 
     } 

     return container; 
    } 

    private static ComponentDataDelegate captureRegistrations(
     IList<Type> unnamedServices, IDictionary<string, Type> namedServices) 
    { 
     return (key, handler) => 
       { 
        if (handler.ComponentModel.Name == handler.ComponentModel.Implementation.FullName) 
        { 
         var text = unnamedServices.Contains(handler.Service) ? "another" : "default"; 
         _log.Info(
          m => m(
            "Registered {2} service for {0} with {1}.", 
            handler.Service.GetDisplayName(), 
            handler.ComponentModel.Implementation.GetDisplayName(), 
            text 
            )); 

         unnamedServices.Add(handler.Service); 
        } 
        else 
        { 
         var text = namedServices.ContainsKey(key) ? "another" : "default"; 
         _log.Info(
          m => m(
            "Registered {3} service {0} with name '{1}' and {2}.", 
            handler.ComponentModel.Service, 
            handler.ComponentModel.Name, 
            handler.ComponentModel.Implementation.GetDisplayName(), 
            text 
            )); 
         namedServices.Add(key, handler.Service); 
        } 
       }; 
    } 

    protected static void tryAddXmlConfig(IWindsorContainer container, string filename) 
    { 
     var fi = Resources.GetFileFromResourceHierarchy(typeof(ApplicationContext).Namespace, filename); 
     if (fi == null) { 
      return; 
     } 
     var configFile = fi.FullName; 
     var xd = immitateFluentApiDefaultIdBehaviour(configFile); 
     container.Install(Configuration.FromXml(new StaticContentResource(xd.OuterXml))); 

    } 

    private static XmlDocument immitateFluentApiDefaultIdBehaviour(string configFile) 
    { 
     var xd = new XmlDocument(); 
     xd.Load(configFile); 

     foreach (
      XmlElement component in 
       xd.SelectNodes("/configuration/components/component[@type and (not(@id) or @id = '')]")) 
     { 
      var type = Type.GetType(component.GetAttribute("type"), true); 
      component.SetAttribute("id", type.FullName); 
     } 

     return xd; 
    } 

    private static IRegistration[] union(
     IList<Type> unnamed, IDictionary<string, Type> named, params Func<IEnumerable<IRegistration>>[] methods) 
    { 
     var all = new List<IRegistration>(); 
     foreach (var method in methods) 
     { 
      foreach (var registration in method()) 
      { 
       var registrationType = registration.GetType(); 
       if (registrationType.IsGenericTypeOf(typeof(ComponentRegistration<>))) 
       { 
        var componentType = registrationType.GetGenericArgumentsFor(typeof(ComponentRegistration<>))[0]; 

        var name = (string)registrationType.GetProperty("Name").GetValue(registration, null); 

        if (name != null) 
        { 
         if (named.ContainsKey(name)) 
         { 
          _log.Debug(
           m => m("Skipped registering default named component {0}.", name)); 
          continue; 
         } 
        } 
        else if (unnamed.Contains(componentType)) 
        { 
         _log.Debug(
          m => m("Skipped registering default component for type {0}.", componentType)); 
         continue; 
        } 

        all.Add(registration); 
       } 
       else 
       { 
        all.Add(registration); 
       } 
      } 
     } 

     return all.ToArray(); 
    } 
} 
0

हाँ, यह एक सेवा का सामान्य कार्यान्वयन को फिर से परिभाषित करता है। आपने यह क्यों किया? इसे फिर से परिभाषित करने के बजाय इसे पहले स्थान पर क्यों पंजीकृत न करें?

क्या आप अधिक संदर्भ प्रदान कर सकते हैं?

+0

मेरे पास एक एक्सएमएल-फाइल है जो धाराप्रवाह वाइरिंग को ओवरराइड करती है। लेकिन मैंने इसे अब XML फ़ाइल को पढ़कर हल किया है और कोड से कॉन्फ़िगरेशन नहीं जोड़ रहा है, जब xml-file उन्हें फिर से परिभाषित करता है। –

+0

यह बेहतर दृष्टिकोण है –

+0

@Lars: क्या आप अधिक विशिष्ट हो सकते हैं कि आप ऐसा कैसे करते हैं? मुझे यहां एक ही समस्या है, मेरे पास मेरी कोर वाइरिंग है और कोर विरिंग को संशोधित करने के बिना किसी एक कार्यान्वयन को दूसरे के साथ स्विच करना चाहता हूं। – Marcus

9

मैं क्रज़ीज़टॉफ से सहमत हूं कि यह आमतौर पर एक अच्छा विचार नहीं है ... हालांकि जहां तक ​​मैं ओवरव्राइट() को डिफ़ॉल्ट घटक को ओवरराइट नहीं कर सकता, यह विशेषता द्वारा परिभाषित जीवनशैली को ओवरराइट करता है (यानी [सिंगलटन]) ।

यदि आप किसी घटक को प्रतिस्थापित करना चाहते हैं, तो आप container.Kernel.RemoveComponent(string key) का उपयोग नए घटक के पंजीकरण के बाद कर सकते हैं।

Here's an example जहां यह समझ में आता है।

+1

यह ध्यान दिया जाना चाहिए कि RemoveComponent हमेशा काम नहीं करता –

+0

@ जॉर्ज: क्या आप उस पर विस्तार कर सकते हैं? इसे तब तक काम करना चाहिए जब तक कोई अन्य घटक हटाए जाने की कोशिश करने वाले व्यक्ति पर निर्भर न हो (0 समझ में आता है) –

+0

आह मैं देखता हूं, लेकिन फिर वैकल्पिक कार्यान्वयन कैसे निर्दिष्ट किया जाए? मैं पूरे ग्राफ को हटाना नहीं चाहता हूं और इसे फिर से जोड़ना चाहता हूं। –

3

यह ऐसी समस्या होगी जो एक सजावटी के साथ कंटेनर सेट करके बेहतर हल हो सकती है, जहां आप स्पष्ट रूप से कार्यान्वयन को बदल सकते हैं सजावटकर्ता कॉल को निर्देशित कर रहा है ... विशेष रूप से यदि आप कार्यान्वयन को प्रतिस्थापित करना चाहते हैं मौजूदा घटकों (यानी सिंगलेट्स) को इंजेक्शन दिया गया है जिसके साथ आपके आवेदन के जीवनकाल के लिए मौजूद हो सकता है।

आपको जो हासिल करने की कोशिश कर रहे हैं उस पर अधिक पृष्ठभूमि की आवश्यकता है।


Here is more information about registering Decorators with Windsor

3

मैं जब एक एकीकरण टेस्ट स्वीट में एक सिस्टम चल रहा एक घटक कार्यान्वयन स्विच करने के लिए की जरूरत है और container.Kernel.RemoveComponent का उपयोग करने में विफल()। तो मैं simple facility के साथ समाप्त हुआ जो मेरे लिए इसका ख्याल रखता है।

+0

दुर्भाग्यवश पंजीकरण के पहले सभी ओवरराइड निर्दिष्ट किए जाने हैं –

11

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

 var sendMailStub = MockRepository.GenerateStub<ISendMail>(); 
     _container.Register(
      Component 
       .For<ISendMail>() 
       .Instance(sendMailStub) 
       .IsDefault() 
      ); 
+0

IsDefault API विंडसर महल असेंबली में उपलब्ध नहीं है। मैं कैसल का जिक्र कर रहा हूं। अधिक असेंबली संस्करण 2.5.1.0। क्या मैं एक पुरानी सभा का जिक्र कर रहा हूं? – RBT

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