কনস্ট্রাক্টর ইনজেকশন কী?


47

আমি (সার্ভিস লোকেটার) নকশার নিদর্শনগুলির নিবন্ধগুলিতে যাওয়ার সময় শর্তাদি কন্সট্রাক্টর ইঞ্জেকশন এবং নির্ভরতা ইনজেকশনটির দিকে নজর রেখেছি।

আমি যখন কন্সট্রাক্টর ইঞ্জেকশন সম্পর্কে গুগল করলাম, তখন আমি অস্পষ্ট ফলাফল পেয়েছি, যা আমাকে এখানে চেক করতে প্ররোচিত করেছে।

কনস্ট্রাক্টর ইনজেকশন কী? এটি কি কোনও নির্দিষ্ট ধরনের নির্ভরতা ইনজেকশন? একটি প্রচলিত উদাহরণ একটি দুর্দান্ত সাহায্য হবে!

সম্পাদন করা

এক সপ্তাহ পর এই প্রশ্নগুলির পুনরায় পর্যালোচনা করে, আমি দেখতে পাচ্ছি যে আমি কীভাবে হারিয়েছি ... অন্য কেউ যদি এখানে পপ করেন তবে আমি আমার সামান্য শিক্ষার সাথে প্রশ্নবোধের আপডেট করব। মন্তব্য / সঠিক নির্দ্বিধায় না দয়া করে। কনস্ট্রাক্টর ইনজেকশন এবং সম্পত্তি ইনজেকশন হ'ল দুটি ধরণের নির্ভরতা ইনজেকশন।


5
গুগলে প্রথম হিট এটি স্পষ্টভাবে ব্যাখ্যা করেছে ... Misko.hevery.com/2009/02/19/…
ব্যবহারকারী 281377

উত্তর:


95

আমি কোনও বিশেষজ্ঞ নই, তবে আমি মনে করি আমি সাহায্য করতে পারি। এবং হ্যাঁ, এটি নির্ভরশীল ইঞ্জেকশনের একটি নির্দিষ্ট ধরণের।

দাবি অস্বীকার : এই প্রায় সবগুলিই নিনেক্ট উইকি থেকে "চুরি" হয়েছিল

আসুন একটি সহজ উদাহরণ দিয়ে হাঁটা দিয়ে নির্ভরতা ইনজেকশন ধারণাটি পরীক্ষা করি। ধরা যাক আপনি পরবর্তী ব্লকবাস্টার গেমটি লিখছেন, যেখানে মহৎ যোদ্ধারা দুর্দান্ত গৌরব অর্জনের জন্য যুদ্ধ করে। প্রথমত, আমাদের আমাদের যোদ্ধাদের সশস্ত্র করার জন্য উপযুক্ত একটি অস্ত্রের প্রয়োজন হবে।

class Sword 
{
    public void Hit(string target)
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

তারপরে, আসুন আমরা আমাদের যোদ্ধাদের উপস্থাপনের জন্য একটি শ্রেণি তৈরি করি। এর শত্রুদের আক্রমণ করার জন্য, যোদ্ধার একটি আক্রমণ () পদ্ধতি প্রয়োজন need এই পদ্ধতিটি যখন ডাকা হয় তখন তার তরোয়ালটি প্রতিপক্ষকে আঘাত করার জন্য ব্যবহার করা উচিত use

class Samurai
{
    readonly Sword sword;
    public Samurai() 
    {
        this.sword = new Sword();
    }

    public void Attack(string target)
    {
        this.sword.Hit(target);
    }
}

এখন, আমরা আমাদের সামুরাই তৈরি করতে পারি এবং যুদ্ধ করতে পারি!

class Program
{
    public static void Main() 
    {
        var warrior = new Samurai();
        warrior.Attack("the evildoers");
    }
}

আপনি যেমন কল্পনা করতে পারেন, এটি চ্যাপ্ট করা দুষ্টুদের কনসোলে অর্ধেকে পরিষ্কার করবে । এটি ঠিক কাজ করে, তবে যদি আমরা আমাদের সামুরাইকে অন্য একটি অস্ত্র দিয়ে সজ্জিত করতে চাই? যেহেতু তরোয়ালটি সামুরাই শ্রেণীর নির্মাণকারীর ভিতরে তৈরি করা হয়েছে, তাই এই পরিবর্তনটি আনতে আমাদের ক্লাসের প্রয়োগটি পরিবর্তন করতে হবে।

যখন কোনও শ্রেণি একটি কংক্রিট নির্ভরতার উপর নির্ভরশীল হয় তখন বলা হয় এটি দৃ class ়ভাবে class শ্রেণীর সাথে মিলিত হয়েছে । এই উদাহরণে, সামুরাই ক্লাসটি তরোয়াল শ্রেণিতে শক্তভাবে মিলিত হয়েছে। যখন ক্লাসগুলি দৃly়ভাবে একত্রিত হয়, তাদের প্রয়োগের পরিবর্তন না করে সেগুলি আদান প্রদান করা যায় না। দৃ classes়ভাবে সংযোজন ক্লাস এড়ানোর জন্য, আমরা ইন্টারফেসগুলি ইন্ডিয়ারেশনের একটি স্তর সরবরাহ করতে পারি। আসুন আমাদের গেমের একটি অস্ত্র প্রতিনিধিত্ব করার জন্য একটি ইন্টারফেস তৈরি করুন।

interface IWeapon
{
    void Hit(string target);
}

তারপরে, আমাদের তরোয়াল শ্রেণি এই ইন্টারফেসটি প্রয়োগ করতে পারে:

class Sword : IWeapon
{
    public void Hit(string target) 
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

এবং আমরা আমাদের সামুরাই ক্লাস পরিবর্তন করতে পারি:

class Samurai
{
    readonly IWeapon weapon;
    public Samurai() 
    {
        this.weapon = new Sword();
    }
    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}

এখন আমাদের সামুরাই বিভিন্ন অস্ত্র দিয়ে সজ্জিত হতে পারে। কিন্তু অপেক্ষা করো! তরোয়ালটি এখনও সামুরাই নির্মাণকারীর ভিতরে তৈরি করা হয়েছে। যেহেতু আমাদের যোদ্ধাকে অন্য একটি অস্ত্র দেওয়ার জন্য আমাদের সামুরাইয়ের বাস্তবায়নে পরিবর্তন আনতে হবে, তবুও সামুরাই তরোয়ার সাথে শক্তভাবে মিলিত led

ভাগ্যক্রমে, একটি সহজ সমাধান আছে। সামুরাইয়ের কনস্ট্রাক্টরের মধ্যে থেকে তরোয়ালটি তৈরি করার পরিবর্তে আমরা এটির পরিবর্তে কনস্ট্রাক্টরের প্যারামিটার হিসাবে প্রকাশ করতে পারি। কনস্ট্রাক্টর ইনজেকশন নামেও পরিচিত।

class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon) 
    {
        this.weapon = weapon;
    }
    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}

জর্জিও যেমন উল্লেখ করেছেন, সেখানে রয়েছে সম্পত্তি ইনজেকশনও। এটি এমন কিছু হবে:

class Samurai
{
    IWeapon weapon;

    public Samurai() { }


    public void SetWeapon(IWeapon weapon)
    {
        this.weapon = weapon;
    }

    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }

}

আশাকরি এটা সাহায্য করবে.


8
এই এক ভালবাসেন! :) এটি আসলে গল্পের মতো পড়ে! উৎসুক. আপনি যদি একই সামুরাইকে একাধিক অস্ত্র দিয়ে সজ্জিত করতে চান (ধারাবাহিকভাবে), সম্পত্তি ইনজেকশনটি সবচেয়ে ভাল উপায় হতে পারে?
TheSilverBullet

হ্যাঁ, আপনি এটি করতে পারে। আসলে, আমি মনে করি আপনাকে অ্যাটাক পদ্ধতিতে প্যারামিটার হিসাবে IWeapon দেওয়ার চেয়ে আরও ভাল পরিবেশিত হবে। "পাবলিক অকার্যকর অ্যাটাকের মতো (স্ট্রিং টার্গেট সহ আইওয়াইপন)"। এবং সদৃশ কোড এড়ানোর জন্য আমি বিদ্যমান পদ্ধতিটিকে "পাবলিক অকার্যকর আক্রমণ (স্ট্রিং টার্গেট)" অক্ষত করে এটিকে "এটি.এটাক (এই.ওয়েপন, টার্গেট)" বলব।
লুইজ অ্যাঞ্জেলো

এবং তারপরে কারখানার সাথে মিলিত হয়ে আপনি ক্রিয়েটওয়ার্ডসামুরাই () এর মতো পদ্ধতিগুলি পেতে পারেন! চমৎকার উদাহরণ।
গেরটেন

2
দুর্দান্ত উদাহরণ! এত পরিষ্কার ...
সার্জ ভ্যান ড্যান ওভার এভার

@ লুইজ অ্যাঞ্জেলো দুঃখিত, আমি নিশ্চিত নই যে আমি আপনার মন্তব্যটি বুঝতে পেরেছি: "আসলে, আমি মনে করি আপনাকে অ্যাটাক পদ্ধতিতে প্যারামিটার হিসাবে IWeapon পাস করার চেয়ে আরও ভাল পরিবেশিত হবে Like লাইক .."। আপনি সামুরাই ক্লাসে অ্যাটাক পদ্ধতিটি বোঝাচ্ছেন?
পাপ

3

আমি এটিকে খুব প্রাথমিক করার জন্য যথাসম্ভব চেষ্টা করব। এইভাবে, আপনি ধারণাটি তৈরি করতে এবং আপনার নিজস্ব জটিল সমাধান বা ধারণা তৈরি করতে পারেন।

এখন কল্পনা করুন আমাদের জুবিলী নামে একটি গির্জা রয়েছে, যার শাখা বিশ্বব্যাপী রয়েছে। আমাদের লক্ষ্য হ'ল প্রতিটি শাখা থেকে কোনও আইটেম পাওয়া। এখানে ডিআই এর সাথে সমাধান হবে;

1) একটি ইন্টারফেস আইজবিলি তৈরি করুন:

public interface IJubilee
{
    string GetItem(string userInput);
}

২) একটি শ্রেণি জুবলিডিআই তৈরি করুন যা আইজবলী ইন্টারফেসকে একজন নির্মাতা হিসাবে গ্রহণ করবে এবং কোনও আইটেম ফিরিয়ে দেবে:

public class JubileeDI
{
    readonly IJubilee jubilee;

    public JubileeDI(IJubilee jubilee)
    {
        this.jubilee = jubilee;
    }

    public string GetItem(string userInput)
    {
        return this.jubilee.GetItem(userInput);
    }
}

৩) এখন জুবিলিটি, জুবিলিওটি, জুবিলিওভি নামে তিনটি ব্র্যাচ তৈরি করুন, যা সমস্ত আইজবিলি ইন্টারফেসের অধিকারী। এর মজাদার জন্য, এর মধ্যে একটিরটিকে এর পদ্ধতিটি ভার্চুয়াল হিসাবে বাস্তবায়ন করুন:

public class JubileeGT : IJubilee
{
    public virtual string GetItem(string userInput)
    {
        return string.Format("For JubileeGT, you entered {0}", userInput);
    }
}

public class JubileeHOG : IJubilee
{
    public string GetItem(string userInput)
    {
        return string.Format("For JubileeHOG, you entered {0}", userInput);
    }
}

public class JubileeCOV : IJubilee
{
    public string GetItem(string userInput)
    {
        return string.Format("For JubileCOV, you entered {0}", userInput);
    }
}

public class JubileeGTBranchA : JubileeGT
{
    public override string GetItem(string userInput)
    {
        return string.Format("For JubileeGT branch A, you entered {0}", userInput);
    }
}

4) এটাই! এখন আসুন ডিআই-কে কার্যকর অবস্থায় দেখি:

        JubileeDI jCOV = new JubileeDI(new JubileeCOV());
        JubileeDI jHOG = new JubileeDI(new JubileeHOG());
        JubileeDI jGT = new JubileeDI(new JubileeGT());
        JubileeDI jGTA = new JubileeDI(new JubileeGTBranchA());

        var item = jCOV.GetItem("Give me some money!");
        var item2 = jHOG.GetItem("Give me a check!");
        var item3 = jGT.GetItem("I need to be fed!!!");
        var item4 = jGTA.GetItem("Thank you!");

ধারক শ্রেণীর প্রতিটি উদাহরণের জন্য, আমরা আমাদের প্রয়োজনীয় ক্লাসের একটি নতুন উদাহরণ পাস করি, যা আলগা দম্পতি সক্ষম করে।

আশা করি এটি সংক্ষেপে ব্যাখ্যাটি ব্যাখ্যা করবে।


2

মনে করুন যে আপনার Aপ্রতিটি ক্লাস রয়েছে যার প্রতিটি ক্লাসের জন্য অন্য শ্রেণির উদাহরণ প্রয়োজন B

class A
{
   B b;
}

নির্ভরতা ইনজেকশন মানে রেফারেন্সটি Bসেই অবজেক্টের দ্বারা সেট করা হয় যা দৃষ্টান্ত পরিচালনা করে A(ক্লাসটি সরাসরি Aরেফারেন্স পরিচালনা করে এমনটি করার বিপরীতে B)।

কনস্ট্রাক্টর ইনজেকশন মানে রেফারেন্সটি কনস্ট্রাক্টরের কনস্ট্রাক্টরের Bপ্যারামিটার হিসাবে পাস এবং কনস্ট্রাক্টরে Aসেট করা হয়েছে:

class A
{
    B b;

    A(B b)
    {
        this.b = b;
    }
}

বিকল্পটি হ'ল রেফারেন্স সেট করতে একটি সেটার পদ্ধতি (বা কোনও সম্পত্তি) ব্যবহার করা B। এই ক্ষেত্রে, যে অবজেক্টটি একটি দৃষ্টান্ত পরিচালনা করে aতাকে Aঅবশ্যই প্রথমে কনস্ট্রাক্টরকে কল করতে হবে Aএবং পরে সেটার পদ্ধতিটি কল করার A.bআগে সদস্য ভেরিয়েবলটি aব্যবহার করার আগে সেট করতে হবে । যদি একটি দৃষ্টান্ত যখন বস্তু, একে অপরের যেমন করতে আবর্তনশীল উল্লেখ থাকতে আধুনিক ইনজেকশন পদ্ধতি প্রয়োজনীয় bএর Bযে একটি দৃষ্টান্ত সেট করা হয় aএর Aজন্য একটি আগের উল্লেখ রয়েছে a

** সম্পাদনা করুন **

মন্তব্যটি সম্বোধনের জন্য আরও কিছু বিশদ এখানে।

1. ক্লাস এ বি উদাহরণ পরিচালনা করে

class A
{
    B b;

    A()
    {
        b = new B();
    }
 }

২. বি উদাহরণটি কনস্ট্রাক্টরে সেট করা আছে

class A
{
    B b;

    A(B b)
    {
        this.b = b;
    }
}

class M
{
    ...
    B b = new B();
    A a = new A(b);
}

৩. বি উদাহরণটি সেটার পদ্ধতি ব্যবহার করে সেট করা আছে

class A
{
    B b;

    A()
    {
    }

    void setB(B b)
    {
        this.b = b;
    }
}

class M
{
    ...
    B b = new B();
    A a = new A();

    a.setB(b);
}

... ক্লাস এ সরাসরি বিয়ের রেফারেন্স পরিচালনা করার বিপরীতে । এটার মানে কি? আপনি কোডে এটি কিভাবে করবেন? (আমার অজ্ঞতা ক্ষমা করুন।)
TheSilverBullet

1
সমুরাই উদাহরণটি আরও ভাল। আসুন সবাই ভেরিয়েবলের জন্য অক্ষর ব্যবহার বন্ধ করুন ...
স্টুয়ার্টডটনেট

@ স্টুয়ার্ডডোটনেট: সামুরাই উদাহরণটি আরও খারাপ হওয়ার বিষয়ে আমি বিতর্ক করি না, তবে কেন এক-বর্ণের ভেরিয়েবল ব্যবহার বন্ধ করবো? যদি ভেরিয়েবলগুলির কোনও নির্দিষ্ট অর্থ না থাকে তবে কেবল স্থানধারক হয় তবে একক-বর্ণের ভেরিয়েবলগুলি অনেক বেশি কমপ্যাক্ট এবং বিন্দুতে। নাম দীর্ঘতর করার জন্য itemAবা দীর্ঘ নাম ব্যবহার করা objectAসর্বদা ভাল হয় না।
জর্জিও

1
তারপরে আপনি আমার
বক্তব্যটি

@ স্টুয়ার্টডনেট: আমি মনে করি না যে আমি আপনার বক্তব্য মিস করেছি: আপনি দাবি করেন যে বর্ণনামূলক নামগুলি সর্বদা ভাল এবং কোডকে সর্বদা আরও পঠনযোগ্য এবং স্ব-ব্যাখ্যাযোগ্য করে তোলে।
জর্জিও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.