2014-10-17 6 views
11

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


मान लें कि मेरे पास वेब एपीआई के साथ एक एमवीसी प्रोजेक्ट है। मैं निम्नलिखित वस्तुओं है:

  • MyDbContext: मेरी इकाई कोड पहले db संदर्भ
  • IMyDataProvider MyDataProvider द्वारा कार्यान्वित: क्वेरी तर्क शामिल है और का उपयोग करता है MyDbContext
  • MyController: MVC नियंत्रक IMyDataProvider का उपयोग करता है
  • MyApiController: WebAPI नियंत्रक जो IMyDataProvider

क्या मुझे प्रत्येक प्रकार की जीवनशैली के लिए एक कंटेनर बनाना और कॉन्फ़िगर करना चाहिए?

जब मैं RegisterPerWebRequest<T> के साथ सबकुछ पंजीकृत करता हूं तो दोनों प्रकार के नियंत्रकों में काम करता है। क्या यह सुरक्षित है? या वेब एपीआई नियंत्रक में async/await का उपयोग करते समय मैं परेशानी में भाग जाऊंगा?

मेरे पास एमवीसी और वेब एपीआई नियंत्रक दोनों हैं जो एक ही उदाहरण इंजेक्शन देते हैं तो सबसे अच्छा कॉन्फ़िगरेशन क्या होता है?

क्या मुझे एक संकर जीवनशैली का उपयोग करना चाहिए?


अब चीजों को जटिल करने के लिए ... हमारा एप्लिकेशन पृष्ठभूमि कार्यों और सिग्नलआर का भी उपयोग करता है।

इनमें से दोनों कभी-कभी WebRequest के बाहर होते हैं और ऊपर वर्णित वही ऑब्जेक्ट तक पहुंच की आवश्यकता होती है।

लाइफटाइम गुंजाइश का उपयोग करने का सबसे अच्छा समाधान होगा?

क्या मुझे उस जीवन शैली के लिए एक नया कंटेनर बनाने की आवश्यकता होगी? या मैं अपने एमवीसी/वेब एपीआई कंटेनर का पुन: उपयोग/पुन: कॉन्फ़िगर कर सकता हूं?

क्या कोई तिहाई जीवनशैली है?

उत्तर

4

आमतौर पर आपको प्रति जीवन शैली में एक कंटेनर रखने की आवश्यकता नहीं होती है; आम तौर पर आप प्रति AppDomain एक कंटेनर उदाहरण चाहते हैं। हालांकि, एमवीसी के साथ एक ही प्रोजेक्ट में वेब एपीआई मिश्रण एक वास्तुशिल्प बिंदु से एक भयानक विचार आईएमओ (जैसा कि here, here, और here समझाया गया है) से है। इसलिए यदि आप उन हिस्सों को अपने स्वयं के वास्तुशिल्प ब्लॉक में अलग कर रहे हैं, तो आपको पहले से ही कम समस्याएं मिलेंगी।

लेकिन यदि आप एक ही प्रोजेक्ट में एमवीसी और वेब एपीआई चला रहे हैं, तो इसका मूल रूप से मतलब है कि आप हमेशा वेब एपीआई का उपयोग करेंगे। WebApiRequestLifestyle को काम करने के लिए स्पष्ट रूप से बनाया गया था:

आईआईएस के अंदर और बाहर दोनों अच्छी तरह से। यानी यह स्व-होस्टेड वेब एपीआई प्रोजेक्ट में काम कर सकता है जहां कोई HttpContext.Current नहीं है। (source)

सामान्य में, यह आप समानांतर आपरेशन के स्पिन का कोई इरादा नहीं ConfigureAwait(false) (जो वास्तव में दुर्लभ होना चाहिए IMO) का उपयोग कर जब मामले में WebRequestLifestyle आप केवल IIS में चल रहे हैं का उपयोग करने के रूप में समझाया सुरक्षित है here

तो इस मामले में आप अभी भी एक ही प्रोजेक्ट में एमवीसी के साथ वेब एपीआई मिश्रण कर रहे हैं, hybrid lifestyle का उपयोग करने का कोई कारण नहीं है; आप बस एक ही जीवनशैली का उपयोग कर सकते हैं। पृष्ठभूमि प्रसंस्करण करने के लिए आपको हालांकि हाइब्रिड लाइफस्टाइल बनाने की आवश्यकता हो सकती है, लेकिन प्रत्येक परिदृश्य को एक अलग संकर की आवश्यकता होती है। हालांकि, संकरों को ढेर किया जा सकता है और यदि आवश्यक हो तो आप आसानी से 'ट्रिपल लाइफस्टाइल' बना सकते हैं।

चूंकि आप सिग्नलआर के साथ पृष्ठभूमि प्रसंस्करण करना चाहते हैं, इसलिए आपको यह तय करना होगा कि किस पृष्ठभूमि प्रकार को चलाने के लिए scoped lifestyle है। सबसे स्पष्ट जीवन शैली LifetimeScopeLifestyle है और यह आप निम्नलिखित दायरे वाला जीवन शैली का उपयोग कर अपने scoped पंजीकरण करना चाहिए मतलब है:

var hybridLifestyle = Lifestyle.CreateHybrid(
    lifestyleSelector:() => HttpContext.Current != null, 
    trueLifestyle: new WebRequestLifestyle(), 
    falseLifestyle: new LifetimeScopeLifestyle()); 

एक आजीवन गुंजाइश हालांकि स्पष्ट रूप से शुरू किया जा करने की जरूरत है (के रूप में थे वेब अनुरोध गुंजाइश आप के लिए परोक्ष प्रारंभ करे यदि आप अपने वेब एप्लिकेशन में SimpleInjector.Integration.Web.dll शामिल करते हैं)। यह कैसे करें आपके डिजाइन पर निर्भर करता है, लेकिन this q/a about SignalR आपको सही दिशा में इंगित कर सकता है।

+0

मुझे पता था कि एमवीसी और वेबएपीआई समान नहीं थे लेकिन मुझे कहना होगा कि मुझे यह जानकर आश्चर्य हुआ कि यह एक ही प्रोजेक्ट में मिश्रण करने के लिए खराब डिजाइन है। यह देखते हुए कि वे एमवीसी 6 में विलय हो जाएंगे, मैं इस वास्तुकला के साथ रहने में सक्षम हूं। हाइब्रिड लाइफस्टाइल का उपयोग एमवीसी, वेबएपीआई और सिग्नलआर/बीजी टास्क के साथ सिम्पलजे इंजेक्टर का उपयोग करने का सबसे आसान तरीका प्रतीत होता है। हालांकि मुझे _lifestyleSelector_ को निम्नानुसार बदलने की आवश्यकता है: 'कंटेनर। गेटक्रोरेंट लाइफटाइमस्कोप() == नल और& HttpContext.Current! = Null' जब यह मौजूद है तो यह स्पष्ट रूप से दायरे का उपयोग करने के लिए होता है, भले ही कोई HttpContext मौजूद हो (सिग्नल अनुरोध के अंदर) – Chris

7

मुझे कहना है, मैं कुछ समय पहले इसी तरह के परिदृश्य पर ठोकर खा रहा था, मैं अपने वेब एपीआई और सिग्नलआर पर अपनी कॉन्फ़िगरेशन साझा करके समाप्त हुआ, लेकिन आपको सिग्नलआर के लिए कस्टम लाइफस्टाइल लागू करने की आवश्यकता है क्योंकि यह वेब अनुरोध पर आधारित नहीं है ।

विशेष रूप से सिग्नलआर में आपको एक हब में प्रति-वेब-अनुरोध निर्भरताओं को संभालने में कुछ समस्याएं मिलेंगी, उनमें से कुछ httpContext.Current की तरह शून्य हो जाएंगी।

समाधान:

आप WebRequestLifestlye और या तो Lifestyle.Transient, Lifestyle.Singleton, या LifetimeScopeLifestyle के बीच एक संकर जीवन शैली की जरूरत है। मैं समाप्त हुआ मैं सजावटी पैटर्न का उपयोग समाप्त कर दिया, आप यह post और यह अन्य post पढ़ सकते हैं।

मेरी डेकोरेटर

public class CommandLifetimeScopeDecorator<T> : ICommandHandler<T> 
    { 
     private readonly Func<ICommandHandler<T>> _handlerFactory; 
     private readonly Container _container; 

     public CommandLifetimeScopeDecorator(
     Func<ICommandHandler<T>> handlerFactory, Container container) 
     { 
      _handlerFactory = handlerFactory; 
      _container = container; 
     } 

     public void Handle(T command) 
     { 
      using (_container.BeginLifetimeScope()) 
      { 
       var handler = _handlerFactory(); // resolve scoped dependencies 
       handler.Handle(command); 
      } 
     } 

    } 

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

मैं signalR

public class MyHubActivator : IHubActivator 
    { 
     private readonly Container _container; 

     public MyHubActivator(Container container) 
     { 
      _container = container; 
     } 

     public IHub Create(HubDescriptor descriptor) 
     { 
      return _container.GetInstance(descriptor.HubType) as IHub; 
     } 
    } 

एक समग्र जड़ फ़ाइल जो है, जहां आप अपनी निर्भरता को संभालने के लिए जा रहे हैं के लिए एक हब उत्प्रेरक का उपयोग कर निर्भरता कामयाब

public CompositRoot(Container container) 
{ 
    _container = container; 
} 
public container Configure() 
{ 
    // _container.Registerall container dependencies 
    return _container; 
} 

तब जब आप अपने ऐप को बूटस्ट्रैप कर रहे हों तो अपनी समग्र रूट कॉन्फ़िगरेशन साझा करें

var compositRoot = new CompositRoot(simpleInjector.Container); //simple injector instance 
compositRoot.Configure(); 

signalR

GlobalHost.DependencyResolver.Register(typeof(IHubActivator),() => new MyHubActivator(compositRoot)); 
लिए

और आप अन्य परियोजनाओं के बीच आपके विन्यास का पुन: उपयोग कर सकते हैं!

मेरे दो सेंट आशा है कि मदद करता है!

+0

धन्यवाद, आपका उत्तर भी सही है लेकिन एक बड़ा वास्तुशिल्प परिवर्तन की आवश्यकता है। – Chris

+0

कोई समस्या नहीं है! चियर्स! –

+0

जैक, मुझे एक ही समस्या है, क्या आपके पास शेयर के लिए गिट पर यह समाधान है? धन्यवाद – rsegovia

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