2012-12-06 19 views
6

मैं एक एएसपी.नेट एमवीसी प्रोजेक्ट पर काम कर रहा हूं जो बाहरी प्लगइन का समर्थन करता है, अब, मैं यूनिटी से ऑटोफैक में जा रहा हूं और मुझे ऑटोफैक की आजीवन वस्तुओं को लपेटने की ज़रूरत है ताकि प्लगइन्स को इसका संदर्भ, एकता में मैं कुछ ऐसा कर सकता था।ऑटोफैक लाइफटाइम प्रबंधन

public sealed class UnityScopeFactory : IDependencyScopeFactory 
{ 
    private HttpRequestScope _httpRequest; 

    private SingletonScope _singleton; 

    private TransientScope _transient; 

    public IDependencyScope HttpRequest() 
    { 
     return _httpRequest ?? (_httpRequest = new HttpRequestScope()); 
    } 

    public IDependencyScope Singleton() 
    { 
     return _singleton ?? (_singleton = new SingletonScope()); 
    } 

    public IDependencyScope Transient() 
    { 
     return _transient ?? (_transient = new TransientScope()); 
    } 

    private class HttpRequestScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new HttpPerRequestLifetimeManager(); 
     } 
    } 

    private class SingletonScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new ContainerControlledLifetimeManager(); 
     } 
    } 

    private class TransientScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new TransientLifetimeManager(); 
     } 
    } 
} 

मैं Autofac में इसी तरह की बात की है लेकिन मुझे यकीन है कि क्या यह है कि, मैं Autofac के RegistrationBuilder जो (दुर्भाग्य से) आंतरिक है में देखा है और मैं इस के साथ आया था ऐसा करने का सही तरीका नहीं है नहीं कर रहा हूँ।

public class AutofacScopeFactory : IDependencyScopeFactory 
{ 
    private HttpRequestScope _httpRequest; 

    private SingletonScope _singleton; 

    private TransientScope _transient; 

    public IDependencyScope HttpRequest() 
    { 
     return _httpRequest ?? (_httpRequest = new HttpRequestScope()); 
    } 

    public IDependencyScope Singleton() 
    { 
     return _singleton ?? (_singleton = new SingletonScope()); 
    } 

    public IDependencyScope Transient() 
    { 
     return _transient ?? (_transient = new TransientScope()); 
    } 

    private class HttpRequestScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new CurrentScopeLifetime(); 
     } 
    } 

    private class SingletonScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new RootScopeLifetime(); 
     } 
    } 

    private class TransientScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new CurrentScopeLifetime(); 
     } 
    } 
} 

इसके अलावा, के बाद मैं इस काम मिल गया, मैं कैसे ContainerBuilder को इसे पारित कर सकते हैं?

एकता में मैं ऐसा कुछ कर सकता था।

public sealed class UnityDependencyContainer : IDependencyContainer 
{ 
    private readonly IUnityContainer _container; 

    public UnityDependencyContainer() 
    { 
     _container = new UnityContainer() 
    } 

    public void Register<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract 
    { 
     LifetimeManager manager = scope.CreateScope() as LifetimeManager; 

     if (manager != null) 
     { 
      _container.RegisterType<TContract, TImplementation>(manager); 
     } 
    } 
} 

मैं विधि श्रृंखला में IComponentLifetime का उदाहरण कैसे पास करूं? क्या यह एक मृत अंत है?

public class AutofacContainer : IDependencyContainer 
{ 
    private static readonly ContainerBuilder Builder; 

    static AutofacContainer() 
    { 
     Builder = new ContainerBuilder(); 
    } 

    public void RegisterType<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract 
    { 
     IComponentLifetime manager = scope.CreateScope() as IComponentLifetime; 

     if (manager != null) 
     { 
      Builder.RegisterType<TImplementation>().As<TContract>(); 
     } 
    } 
} 

उत्तर

9

Autofac काफी जिस तरह से आप यह उल्लिखित है अलग नहीं है स्कोप, तो आप एक गोल छेद में एक वर्ग खूंटी फिट करने की कोशिश हो सकती है।

ऑटोफैक स्कॉप्स अधिक श्रेणीबद्ध हैं। किसी भी जीवनकाल के दायरे में बच्चे के क्षणिक दायरे पैदा हो सकते हैं। उदाहरण के लिए, आप देख सकते हैं ...

  • कंटेनर/जड़ जीवन
    • HttpRequest गुंजाइश
      • छोटे कार्य विशेष के क्षणिक गुंजाइश

आप एक स्कोप "टैग" कर सकते हैं और एक एसपी में घटक पंजीकृत कर सकते हैं विशिष्ट नामित/टैग किए गए दायरे - इस तरह HttpRequest स्कोप काम करता है। यह एक विशेष पहचानकर्ता के साथ "टैग" हो जाता है।

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

नोट: यह चर्चा यह कैसे काम करती है इसका सकल ओवरम्प्लिफिकेशन है।There is documentation explaining the lifetime scope mechanism on the Autofac site.

प्वाइंट होने के नाते, मुझे उपरोक्त डिज़ाइन में कुछ चीजें दिखाई देती हैं जो ऑटोफैक सामग्री के साथ वास्तव में "जिव" नहीं करती हैं।

निर्भरतास्कोप फैक्ट्री अपने स्वयं के क्षणिक या HttpRequest scopes नहीं बना सकता है। विशिष्ट जीवनकाल प्रबंधन घटक हैं जो HttpRequest स्कोप को प्रारंभ और समाप्त करते हैं, इसलिए आपको उनको उपयोग करने की आवश्यकता होगी; कोई 'वैश्विक' क्षणिक दायरा नहीं है, इसलिए आप वास्तव में केवल एक नहीं बना सकते हैं।

HttpRequest गुंजाइश, आप MVC का उपयोग कर रहे हैं की तरह अधिक देखें, माना, ...

public ILifetimeScope HttpRequestScope 
{ 
    get { return AutofacDependencyResolver.Current.RequestLifetime; } 
} 

एक क्षणिक क्षेत्र के लिए कोई अनुरूप नहीं है क्योंकि उस पर उपयोग इनलाइन माना जाता है:

using(var transientScope = parentScope.BeginLifetimeScope()) 
{ 
    // Do stuff and resolve dependencies using the transient scope. 
    // The IDisposable pattern here is important so transient 
    // dependencies will be properly disposed at the end of the scope. 
} 

जब आप घटक पंजीकृत करते हैं, तो आप उन्हें "जीवनभर के दायरे में पंजीकृत नहीं करते हैं।" आप वास्तव में उन्हें एक घटक रजिस्ट्री में पंजीकृत करते हैं और घटक पंजीकरण के हिस्से में संकल्प के बाद घटक के जीवनकाल के बारे में स्वामित्व जानकारी शामिल होती है।

var builder = new ContainerBuilder(); 

// This component is factory-scoped and will be "owned" by whatever 
// lifetime scope resolves it. You can resolve multiple of these 
// in a single scope: 
builder.RegisterType<FirstComponent>().As<ISomeInterface>(); 

// This component is a singleton inside any given lifetime scope, 
// but if you have a hierarchy of scopes, you'll get one in each 
// level of the hierarchy. 
builder.RegisterType<SecondComponent>().InstancePerLifetimeScope(); 

// This component will be a singleton inside a specifically named 
// lifetime scope. If you try to resolve it in a scope without that 
// name, it'll search up the scope stack until it finds the scope 
// with the right name. If no matching scope is found - exception. 
builder.RegisterType<ThirdComponent>().InstancePerMatchingLifetimeScope("scopename"); 

// This is a per-HTTP-request component. It's just like the 
// above InstancePerMatchingLifetimeScope, but it has a special 
// tag that the web integration knows about. 
builder.RegisterType<FourthComponent>().InstancePerHttpRequest(); 

आप एक कंटेनर/पंजीकरण नास्तिक इंटरफेस बनाने की कोशिश कर रहे हैं, यह एक "जीवन भर गुंजाइश प्रबंधक" की जरूरत नहीं होगी - इसके बजाय, आप कुछ इरादा जीवन भर गुंजाइश संकेत पैरामीटर पास करने के आवश्यकता होगी और इनकमिंग पैरामीटर के आधार पर उपयुक्त पंजीकरण वाक्यविन्यास (ऊपर) करें।

फिर से, I'd recommend you check out that documentation

इसके अलावा, अगर आप एकता का उपयोग कर रहे Autofac एक उद्यम लाइब्रेरी कौन्फ़िगरेटर पैकेज कि (के बाद से है कि कैसे EntLib काम करने के लिए पसंद करती है है) आप एक एकता शैली में Autofac कॉन्फ़िगर कर सकते है। यह जांचने के लिए कुछ हो सकता है।

यदि आपको यूनिटी सिंटैक्स का उपयोग करने की आवश्यकता नहीं है ... मैं केवल देशी ऑटोफैक तरीके से काम करने की अनुशंसा करता हूं। एक कंटेनर बनाने और दूसरे की तरह कार्य करने की कोशिश करना एक बहुत ही दर्दनाक प्रयास है।

मान लें कि आपके प्लगइन अलग-अलग असेंबली में हैं या जो भी हो, आप आसानी से ऑटोफैक मॉड्यूल के साथ कुछ अच्छे असेंबली-स्कैनिंग सिंटैक्स का लाभ उठा सकते हैं और अपने प्लगइन को इस तरह से जोड़ सकते हैं।

+0

वाह! समय लेने के लिए बहुत बहुत धन्यवाद, वास्तव में सराहना की। यह वास्तव में इस चरण में बदलने के लिए पिटा है, मैं ऑटोफैक में बदलने के लिए उत्सुक था और इसे आज़माएं लेकिन अगर मैं इसका उपयोग नहीं कर सकता क्योंकि यह अलग-अलग काम करता है तो मुझे एक और कंटेनर का उपयोग करना होगा या लागत के साथ रहना होगा इसे एटीएम बदलने के लिए बहुत अच्छा है। –

+0

अच्छी व्याख्या +1! –

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