क्या कोई Microsoft एकता की व्याख्या कर सकता है?


157

मैं एमएसडीएन पर एकता (डिपेंडेंसी इंजेक्शन, नियंत्रण का उलटा) के बारे में लेख पढ़ रहा हूं, लेकिन मुझे लगता है कि मुझे इसकी सरल शब्दों (या सरल उदाहरणों) में व्याख्या करने की आवश्यकता है। मैं MVPC पैटर्न से परिचित हूं (हम इसका उपयोग यहां करते हैं), लेकिन मैं अभी तक इस एकता की चीज को वास्तव में समझ नहीं पाया हूं, और मुझे लगता है कि यह हमारे एप्लिकेशन डिजाइन में अगला कदम है।


12
मैं प्यार करता हूँ कि यह "एकता" के समान नाम कैसे है, इसलिए जब मैं एकता गेम इंजन के सामान की खोज कर रहा हूँ तो मैं इस पुराने तकनीक को देखता हूँ, आह। सभी अच्छे बैंड के नाम लिए जाते हैं, मुझे लगता है।
टॉम शुल्ज

2
@ टॉम-स्कुलज़ ओल्ड टेक? nuget.org/packages/Unity - अंतिम बार 5 दिन पहले अपडेट किया गया।
रोजर विल्क्स

जवाबों:


174

एकता सिर्फ एक आईओसी "कंटेनर" है। Google संरचना मानचित्र और इसके बजाय इसे आज़माएँ। थोड़ा सा आसान है, मुझे लगता है, जब IoC सामान आपके लिए नया है।

मूल रूप से, यदि आप IoC को समझते हैं तो आप समझते हैं कि आप जो कर रहे हैं, वह तब होता है जब कोई ऑब्जेक्ट बन जाता है, उसके लिए नियंत्रण को निष्क्रिय कर देता है।

बिना आईओसी:

public class MyClass
{
   IMyService _myService; 

   public MyClass()
   {
      _myService = new SomeConcreteService();    
   }
}

IoC कंटेनर के साथ:

public class MyClass
{
   IMyService _myService; 

   public MyClass(IMyService myService)
   {
      _myService = myService;    
   }
}

IoC के बिना, आपकी कक्षा जो IMyService पर निर्भर है, को उपयोग करने के लिए सेवा का एक ठोस संस्करण नया करना होगा। और यह कई कारणों से खराब है (आपने अपनी कक्षा को IMyService के एक विशिष्ट ठोस संस्करण के लिए युग्मित किया है, आप इसे आसानी से परीक्षण नहीं कर सकते, आप इसे आसानी से नहीं बदल सकते, आदि)

एक IoC कंटेनर के साथ आप उन निर्भरता को हल करने के लिए कंटेनर को "कॉन्फ़िगर" करते हैं। तो एक कंस्ट्रक्टर-आधारित इंजेक्शन स्कीम के साथ, आप बस इंटरफ़ेस को IMyService निर्भरता में कंस्ट्रक्टर में पास करते हैं। जब आप अपने कंटेनर के साथ MyClass बनाते हैं, तो आपका कंटेनर आपके लिए IMyService निर्भरता को हल करेगा।

संरूपण का उपयोग करते हुए, कन्टेनर का विन्यास इस तरह दिखता है:

StructureMapConfiguration.ForRequestedType<MyClass>().TheDefaultIsConcreteType<MyClass>();
StructureMapConfiguration.ForRequestedType<IMyService>().TheDefaultIsConcreteType<SomeConcreteService>();

इसलिए आपने जो किया है, उसे कंटेनर कहा जाता है, "जब कोई IMyService से अनुरोध करता है, तो उन्हें SomeConrete.ervice की एक प्रति दें।" और आपने यह भी निर्दिष्ट किया है कि जब कोई MyClass के लिए पूछता है, तो उन्हें एक ठोस MyClass मिलता है।

यह सब एक IoC कंटेनर वास्तव में करता है। वे अधिक कर सकते हैं, लेकिन इसका जोर है - वे आपके लिए निर्भरता का समाधान करते हैं, इसलिए आपको (और आपको अपने कोड में "नए" कीवर्ड का उपयोग करने की आवश्यकता नहीं है)।

अंतिम चरण: जब आप अपना MyClass बनाते हैं, तो आप ऐसा करेंगे:

var myClass = ObjectFactory.GetInstance<MyClass>();

उम्मीद है की वो मदद करदे। आप मुझे ईमेल कर सकते हैं।


2
तो यह एक कारखाने की तरह है, मुझे लगता है? अगर मैं इसे सही ढंग से पालन कर रहा हूं, तो क्या आप अंतिम उदाहरण में <MyClass> के बजाय <IMyClass> का उपयोग नहीं करेंगे? इसलिए यह var myClass = ObjectFactory.GetInstance <IMyClass> () होगा? आपकी मदद के लिए धन्यवाद, यह मेरे लिए एक अच्छी शुरुआत है!
रयान एबॉट

3
एक तरह से, यह एक कारखाने की तरह है, हाँ। आपके आवेदन के लिए एक मास्टर फैक्टरी। लेकिन यह सिंगलटेलेट्स सहित विभिन्न प्रकारों के बहुत सारे रिटर्न के लिए कॉन्फ़िगर किया जा सकता है। MyClass को इंटरफ़ेस के लिए - यदि यह एक व्यावसायिक वस्तु है, तो मैं एक इंटरफ़ेस नहीं निकालूंगा। बाकी सब के लिए, मैं आमतौर पर होता।
क्रिस होम्स

क्या होगा यदि आप केवल ObjectFactory.GetInstance <MyClass> () कहते हैं; और आपने SomeConcreteClass को कॉन्फ़िगर नहीं किया है? क्या आपको उस मामले में त्रुटि मिलेगी?
रेवल्वेंस

1
@ रे: यह कंटेनर पर निर्भर करता है। कुछ कंटेनरों को लिखा जाता है ताकि, डिफ़ॉल्ट रूप से, वे एक नामकरण सम्मेलन का उपयोग करें, जैसे कि यदि एक वर्ग का नाम MyClass है और इंटरफ़ेस का नाम IMyInterface है, तो कंटेनर स्वचालित रूप से उस इंटरफ़ेस के लिए उस वर्ग को कॉन्फ़िगर करेगा। तो उस स्थिति में, यदि आप इसे मैन्युअल रूप से कॉन्फ़िगर नहीं करते हैं, तो कंटेनर का डिफ़ॉल्ट "कन्वेंशन" इसे वैसे भी उठाता है। हालाँकि, यदि आपका वर्ग और इंटरफ़ेस कन्वेंशन का पालन नहीं करते हैं और आप उस क्लास के लिए कंटेनर को कॉन्फ़िगर नहीं करते हैं, तो हाँ, आपको रनटाइम में एक त्रुटि मिलती है।
क्रिस होम्स

1
@saravanan मुझे लगता है कि अब स्ट्रक्चर-आधारित नाम-आधारित सम्मेलन करता है। मै निच्षित नहि हु; हमने लंबे समय तक इसका उपयोग नहीं किया है (मैंने अपने व्यवसाय के लिए एक कस्टम लिखा था; यह इंटरफेस और कक्षाओं के लिए समान-नाम सम्मेलन का उपयोग करता है)।
क्रिस होम्स

39

मैंने सिर्फ डेविड हेडन द्वारा 30 मिनट की यूनिटी डिपेंडेंसी इंजेक्शन IoC स्क्रेंकास्ट देखा और महसूस किया कि उदाहरण के लिए एक अच्छा स्पष्टीकरण था। यहाँ शो नोट्स से एक स्निपेट दिया गया है:

पेंचकस एकता आईओसी के कई सामान्य उपयोग दिखाता है, जैसे:

  • कंटेनर में प्रकार नहीं बनाना
  • टाइपिंग को पंजीकृत करना और हल करना
  • नामांकित टाइपिंग को पंजीकृत करना और हल करना
  • सिंगलटन, लाइफटाइम मैनेजर, और कंटेनरकंट्रोलड लाइफटाइम मैनेजर
  • मौजूदा मामलों को पंजीकृत करना
  • मौजूदा उदाहरणों में निर्भरता का इंजेक्शन
  • App.config / Web.config के माध्यम से UnityContainer को आबाद करना
  • निर्भरता विशेषताओं के विपरीत इंजेक्शन एपीआई के माध्यम से निर्भरता निर्दिष्ट करना
  • नेस्टेड (पेरेंट-चाइल्ड) कंटेनरों का उपयोग करना

32

एकता कई अन्य लोगों की तरह एक पुस्तकालय है जो आपको खुद को बनाने के लिए बिना किसी अनुरोधित प्रकार के उदाहरण प्राप्त करने की अनुमति देता है। तो दिया।

public interface ICalculator
{
    void Add(int a, int b);
}

public class Calculator : ICalculator
{
    public void Add(int a, int b)
    {
        return a + b;
    }
}

जब आप ICalculator उर्फ ​​IoC (नियंत्रण का उलटा) प्रकार का अनुरोध किया जाता है (तकनीकी उदाहरण सही नहीं है) के लिए कैलकुलेटर को पंजीकृत करने के लिए आप यूनिटी जैसी लाइब्रेरी का उपयोग करेंगे।

IoCLlibrary.Register<ICalculator>.Return<Calculator>();

तो अब जब आप एक ICalculator का एक उदाहरण आप चाहते हैं बस ...

Calculator calc = IoCLibrary.Resolve<ICalculator>();

आईओसी पुस्तकालयों को आमतौर पर एक प्रकार को हल करने के लिए या तो एक सिंगलटन को पकड़ने या हर बार एक नया उदाहरण बनाने के लिए कॉन्फ़िगर किया जा सकता है।

अब हम कहते हैं कि आपके पास एक ऐसा वर्ग है जो एक ICalculator पर निर्भर करता है जो आपके पास मौजूद हो सकता है।

public class BankingSystem
{
    public BankingSystem(ICalculator calc)
    {
        _calc = calc;
    }

    private ICalculator _calc;
}

और जब आप इसे बनाया जाता है तो आप किसी ऑब्जेक्ट को कंस्ट्रक्टर में इंजेक्ट करने के लिए लाइब्रेरी को सेटअप कर सकते हैं।

तो DI या डिपेंडेंसी इंजेक्शन का मतलब है किसी अन्य वस्तु को इंजेक्ट करना।


ICalculator कैल्क होना चाहिए = IoCLibrary.esolve <ICalculator> ();
शुभरत रायमोव

31

यह आदमी WilcoxTutorials यूनिटी कंटेनर का एक उत्कृष्ट प्रदर्शन देता है जो शुरुआती लोगों के उद्देश्य से है।

भाग 1: http://www.youtube.com/watch?v=CWwe9Z0Gyew

भाग 2: http://www.youtube.com/watch?v=PsIbevgzQQE

आधे घंटे से भी कम समय में और आप मूल बातें समझ जाएंगे!


3
वे वास्तव में सहायक vids थे
gdubs

10

एकता एक आईओसी है। IoC की बात यह है कि स्वयं के बाहर के प्रकारों के बीच निर्भरता की तारों को अमूर्त करना। इसके कुछ फायदे हैं। सबसे पहले, यह केंद्रीय रूप से किया जाता है, जिसका अर्थ है कि निर्भरता बदलने पर आपको बहुत सारे कोड बदलने की ज़रूरत नहीं है (जो कि यूनिट परीक्षणों के लिए मामला हो सकता है)।

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


5

MSDN में एकता का उपयोग करके निर्भरता इंजेक्शन के लिए डेवलपर की मार्गदर्शिका है जो उपयोगी हो सकती है।

डेवलपर की गाइड निर्भरता इंजेक्शन के मूल के साथ शुरू होती है, और निर्भरता इंजेक्शन के लिए एकता का उपयोग कैसे करें के उदाहरणों के साथ जारी है। फरवरी 2014 तक डेवलपर की गाइड यूनिटी 3.0 को कवर करती है, जिसे अप्रैल 2013 में जारी किया गया था।


1

मैं ASP.NET वेब एपीआई 2 में निर्भरता इंजेक्शन के अधिकांश उदाहरणों को कवर कर रहा हूं

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

public class NoShape : IShape
{
    public string Name { get; set; } = "I have No Shape";
}

public class Circle : IShape
{
    public string Name { get; set; } = "Circle";
}

public class Rectangle : IShape
{
    public Rectangle(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; } = "Rectangle";
}

DIAutoV2Controller.cs में ऑटो इंजेक्शन तंत्र का उपयोग किया जाता है

[RoutePrefix("api/v2/DIAutoExample")]
public class DIAutoV2Controller : ApiController
{
    private string ConstructorInjected;
    private string MethodInjected1;
    private string MethodInjected2;
    private string MethodInjected3;

    [Dependency]
    public IShape NoShape { get; set; }

    [Dependency("Circle")]
    public IShape ShapeCircle { get; set; }

    [Dependency("Rectangle")]
    public IShape ShapeRectangle { get; set; }

    [Dependency("PiValueExample1")]
    public double PiValue { get; set; }

    [InjectionConstructor]
    public DIAutoV2Controller([Dependency("Circle")]IShape shape1, [Dependency("Rectangle")]IShape shape2, IShape shape3)
    {
        this.ConstructorInjected = shape1.Name + " & " + shape2.Name + " & " + shape3.Name;
    }

    [NonAction]
    [InjectionMethod]
    public void Initialize()
    {
        this.MethodInjected1 = "Default Initialize done";
    }

    [NonAction]
    [InjectionMethod]
    public void Initialize2([Dependency("Circle")]IShape shape1)
    {
        this.MethodInjected2 = shape1.Name;
    }

    [NonAction]
    [InjectionMethod]
    public void Initialize3(IShape shape1)
    {
        this.MethodInjected3 = shape1.Name;
    }

    [HttpGet]
    [Route("constructorinjection")]
    public string constructorinjection()
    {
        return "Constructor Injected: " + this.ConstructorInjected;
    }

    [HttpGet]
    [Route("GetNoShape")]
    public string GetNoShape()
    {
        return "Property Injected: " + this.NoShape.Name;
    }

    [HttpGet]
    [Route("GetShapeCircle")]
    public string GetShapeCircle()
    {
        return "Property Injected: " + this.ShapeCircle.Name;
    }

    [HttpGet]
    [Route("GetShapeRectangle")]
    public string GetShapeRectangle()
    {
        return "Property Injected: " + this.ShapeRectangle.Name;
    }

    [HttpGet]
    [Route("GetPiValue")]
    public string GetPiValue()
    {
        return "Property Injected: " + this.PiValue;
    }

    [HttpGet]
    [Route("MethodInjected1")]
    public string InjectionMethod1()
    {
        return "Method Injected: " + this.MethodInjected1;
    }

    [HttpGet]
    [Route("MethodInjected2")]
    public string InjectionMethod2()
    {
        return "Method Injected: " + this.MethodInjected2;
    }

    [HttpGet]
    [Route("MethodInjected3")]
    public string InjectionMethod3()
    {
        return "Method Injected: " + this.MethodInjected3;
    }
}

DIV2Controller.cs में सब कुछ निर्भरता कॉन्फ़िगरेशन रिज़ॉल्वर वर्ग से इंजेक्ट किया जाएगा

[RoutePrefix("api/v2/DIExample")]
public class DIV2Controller : ApiController
{
    private string ConstructorInjected;
    private string MethodInjected1;
    private string MethodInjected2;
    public string MyPropertyName { get; set; }
    public double PiValue1 { get; set; }
    public double PiValue2 { get; set; }
    public IShape Shape { get; set; }

    // MethodInjected
    [NonAction]
    public void Initialize()
    {
        this.MethodInjected1 = "Default Initialize done";
    }

    // MethodInjected
    [NonAction]
    public void Initialize2(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
    {
        this.MethodInjected2 = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
    }

    public DIV2Controller(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
    {
        this.ConstructorInjected = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
    }

    [HttpGet]
    [Route("constructorinjection")]
    public string constructorinjection()
    {
        return "Constructor Injected: " + this.ConstructorInjected;
    }

    [HttpGet]
    [Route("PropertyInjected")]
    public string InjectionProperty()
    {
        return "Property Injected: " + this.MyPropertyName;
    }

    [HttpGet]
    [Route("GetPiValue1")]
    public string GetPiValue1()
    {
        return "Property Injected: " + this.PiValue1;
    }

    [HttpGet]
    [Route("GetPiValue2")]
    public string GetPiValue2()
    {
        return "Property Injected: " + this.PiValue2;
    }

    [HttpGet]
    [Route("GetShape")]
    public string GetShape()
    {
        return "Property Injected: " + this.Shape.Name;
    }

    [HttpGet]
    [Route("MethodInjected1")]
    public string InjectionMethod1()
    {
        return "Method Injected: " + this.MethodInjected1;
    }

    [HttpGet]
    [Route("MethodInjected2")]
    public string InjectionMethod2()
    {
        return "Method Injected: " + this.MethodInjected2;
    }
}

निर्भरता रिज़ॉल्वर को कॉन्फ़िगर करना

public static void Register(HttpConfiguration config)
{
    var container = new UnityContainer();
    RegisterInterfaces(container);
    config.DependencyResolver = new UnityResolver(container);

    // Other Web API configuration not shown.
}

private static void RegisterInterfaces(UnityContainer container)
{
    var dbContext = new SchoolDbContext();
    // Registration with constructor injection
    container.RegisterType<IStudentRepository, StudentRepository>(new InjectionConstructor(dbContext));
    container.RegisterType<ICourseRepository, CourseRepository>(new InjectionConstructor(dbContext));

    // Set constant/default value of Pi = 3.141 
    container.RegisterInstance<double>("PiValueExample1", 3.141);
    container.RegisterInstance<double>("PiValueExample2", 3.14);

    // without a name
    container.RegisterInstance<IShape>(new NoShape());

    // with circle name
    container.RegisterType<IShape, Circle>("Circle", new InjectionProperty("Name", "I am Circle"));

    // with rectangle name
    container.RegisterType<IShape, Rectangle>("Rectangle", new InjectionConstructor("I am Rectangle"));

    // Complex type like Constructor, Property and method injection
    container.RegisterType<DIV2Controller, DIV2Controller>(
        new InjectionConstructor("Constructor Value1", container.Resolve<IShape>("Circle"), "Constructor Value2", container.Resolve<IShape>()),
        new InjectionMethod("Initialize"),
        new InjectionMethod("Initialize2", "Value1", container.Resolve<IShape>("Circle"), "Value2", container.Resolve<IShape>()),
        new InjectionProperty("MyPropertyName", "Property Value"),
        new InjectionProperty("PiValue1", container.Resolve<double>("PiValueExample1")),
        new InjectionProperty("Shape", container.Resolve<IShape>("Rectangle")),
        new InjectionProperty("PiValue2", container.Resolve<double>("PiValueExample2")));
}

यह कई कारणों से विशेष रूप से उपयोगी उत्तर नहीं है। यह एक अनावश्यक रूप से जटिल उदाहरण है जिसमें IOC की एक सरल व्याख्या की पेशकश करने में उपयोगी होने के लिए बहुत अधिक कोड है। इसके अलावा, कोड उन जगहों पर स्पष्ट रूप से प्रलेखित नहीं है जहां आपको वास्तव में इसकी आवश्यकता होगी।
डेन एटकिन्सन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.