2010-12-09 15 views
8

मैं एएसपी.नेट एमवीसी प्रोजेक्ट में कैसल विंडसर 2.5.1 का उपयोग कर रहा हूं और एक ऑब्जेक्ट बनाने के लिए प्रॉपर्टी इंजेक्शन का उपयोग कर रहा हूं जिसे मैं बेस नियंत्रक वर्ग पर हमेशा उपलब्ध होने की उम्मीद करता हूं। मैं इस ऑब्जेक्ट को बनाने के लिए एक फैक्ट्री का उपयोग कर रहा हूं, हालांकि अगर कन्स्ट्रक्टर में कोई त्रुटि है, तो मुझे विंडसर से चेतावनी नहीं मिलती है और यह सिर्फ मेरी ऑब्जेक्ट देता है लेकिन संपत्ति इंजेक्शन के बिना।कैसल विंडसर अजीब व्यवहार wth संपत्ति इंजेक्शन और फैक्टरी विधि

क्या यह अपेक्षित व्यवहार है, और यदि हां, तो कोई कारखाना कुछ भी वापस करने में विफल होने पर मुझे कोई त्रुटि कैसे प्राप्त हो सकती है?

यहाँ एक उदाहरण

public class MyDependency : IMyDependency 
{ 
    public MyDependency(bool error) 
    { 
     if (error) throw new Exception("I error on creation"); 
    } 
} 

public interface IMyDependency 
{ 
} 

public class MyConsumer 
{ 
    public IMyDependency MyDependency { get; set; } 
} 

[TestFixture] 
public class ProgramTest 
{ 
    [Test] 
    public void CreateWithoutError() //Works as expected 
    { 
     var container = new WindsorContainer().Register(
      Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(false)).LifeStyle.Transient, 
      Component.For<MyConsumer>().LifeStyle.Transient 
     ); 

     var consumer = container.Resolve<MyConsumer>(); 

     Assert.IsNotNull(consumer); 
     Assert.IsNotNull(consumer.MyDependency); 
    } 

    [Test] 
    public void CreateWithError_WhatShouldHappen() //I would expect an error since it can't create MyDependency 
    { 
     var container = new WindsorContainer().Register(
      Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(true)).LifeStyle.Transient, 
      Component.For<MyConsumer>().LifeStyle.Transient 
     ); 

     Assert.Throws<Exception>(() => container.Resolve<MyConsumer>()); 
    } 

    [Test] 
    public void CreateWithError_WhatActuallyHappens() //Gives me back a consumer, but ignores MyDependency 
    { 
     var container = new WindsorContainer().Register(
      Component.For<IMyDependency>().UsingFactoryMethod(() => new MyDependency(true)).LifeStyle.Transient, 
      Component.For<MyConsumer>().LifeStyle.Transient 
     ); 

     var consumer = container.Resolve<MyConsumer>(); 

     Assert.IsNotNull(consumer); 
     Assert.IsNull(consumer.MyDependency); //Basically fails silently! 
    } 
} 

एक दिलचस्प अवलोकन है, अगर मैं अपने MVC आवेदन में इस का उपयोग, मैं जब ReleaseComponent बुला विंडसर से एक आंतरिक त्रुटि मिलती है - तो भले ही यह मुझे वापस नहीं दिया एक मेरी निर्भरता के साथ वर्ग इंजेक्शन, यह अभी भी इसे जारी करने की कोशिश करता प्रतीत होता है।

उत्तर

5

जहाँ तक मुझे पता है, हाँ, यह इरादा व्यवहार है। यह कारखाने के तरीकों के लिए विशिष्ट नहीं है, यह सभी वैकल्पिक सेवा निर्भरताओं के लिए ऐसा काम करता है। वैकल्पिक निर्भरता जो हल करने पर फेंकती हैं उन्हें गैर-समाधान योग्य माना जाता है। यह DefaultComponentActivator.ObtainPropertyValue()

में परिभाषित किया गया है बेशक, यदि आप इस व्यवहार को बदलना चाहते हैं तो आप हमेशा अपने आप के साथ डिफ़ॉल्ट सक्रियकर्ता को ओवरराइड कर सकते हैं।

+1

धन्यवाद, उत्तर स्पॉट पर है! मैं इसे दो तरीकों से काम कर सकता हूं ताकि कोई समस्या न हो – amarsuperstar

+1

यहां यह एक तरीका है: http://stackoverflow.com/a/12007547/114029 –

5

साथ ही मॉरीसिओ द्वारा सुझाए गए विकल्प के साथ, this सुविधाओं के बारे में उदाहरण पृष्ठ पर समझाए गए अपेक्षित व्यवहार को प्राप्त करने के लिए सुविधा बनाना भी संभव है।

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
public class NonOptionalAttribute : Attribute 
{ 
} 

public class NonOptionalPropertiesFacility : AbstractFacility 
{ 
    protected override void Init() 
    { 
     Kernel.ComponentModelBuilder.AddContributor(new NonOptionalInspector()); 
    } 
} 

public class NonOptionalInspector : IContributeComponentModelConstruction 
{ 
    public void ProcessModel(IKernel kernel, ComponentModel model) 
    { 
     foreach (var prop in model.Properties.Where(prop => prop.Property.IsDefined(typeof (NonOptionalAttribute), false))) 
     { 
      prop.Dependency.IsOptional = false; 
     } 
    } 
} 

तो बस [NonOptional] के साथ किसी भी गुण सजाने और अगर वहाँ निर्माण के साथ एक मुद्दा है तो आपको एक त्रुटि प्राप्त होगा:

यहाँ मेरी कार्यान्वयन जो थोड़ा अधिक संक्षिप्त है।

+1

बिल्कुल सही! अगर कोई भी पढ़ाई सुविधाओं को स्थापित करने के लिए सिंटैक्स को याद नहीं रख सकता है (जैसे मेरे), तो बस अपने बूटस्ट्रैप दिनचर्या के दौरान कंटेनर को कॉल करें। एडफैक्शिलिटी () –

0

कैसल विंडसर 3.2 के रूप में Diagnostic logging in the container नया ठंडा जोड़ा है।

तो तुम एक ASP.NET MVC अनुप्रयोग में उदाहरण के लिए ऐसा करते हैं, तो:

var logger = _container.Resolve<ILogger>(); 
((IKernelInternal)_container.Kernel).Logger = logger; 

आप लॉग आपके लिए कॉन्फ़िगर किया गया log4net लकड़हारा के लिए विंडसर द्वारा पकड़ा अनुप्रेषित कर सकते हैं।

जानकारी के प्रकार वर्तमान में लॉग किया जा रहा शामिल हैं:

  • जब विंडसर (संपत्ति इंजेक्शन) की तरह एक वैकल्पिक निर्भरता को हल करने की कोशिश करता है, लेकिन कोई अपवाद के कारण विफल रहता है, अपवाद लॉग होता है।
  • जब किसी प्रकार के सम्मेलन द्वारा पंजीकरण किया जाता है और उस प्रकार के मौजूदा पंजीकरण के कारण इसे अनदेखा कर दिया जाता है, तो यह तथ्य लॉग होता है।