प्रौद्योगिकी साझेदारी

WPF/C#: WPF मध्ये निर्भरता-इञ्जेक्शन् कथं कार्यान्वितुं शक्यते

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

प्रस्तावना

अस्मिन् लेखे WPF Gallery परियोजनायाः उपयोगेन निर्भरता-इञ्जेक्शनस्य सम्बन्धित-अवधारणाः ज्ञातुं शक्यते तथा च WPF मध्ये निर्भरता-इञ्जेक्शन् कथं कर्तव्यम् इति ज्ञातुं शक्यते ।

आश्रयः इन्जेक्शन इति किम्

निर्भरता-इञ्जेक्शन् (DI) इति एकः डिजाइन-प्रतिमानः अस्ति यस्य उपयोगः नियन्त्रणस्य उल्टा (IoC) सिद्धान्तस्य कार्यान्वयनार्थं भवति । निर्भरता-इञ्जेक्शनस्य मुख्यं उद्देश्यं वस्तुनः निर्माणं वस्तुनां मध्ये आश्रयस्य प्रबन्धनं च वस्तुनः अन्तः बाह्यपात्रे अथवा ढाञ्चे स्थानान्तरयितुं भवति, तस्मात् कोडस्य परिपालनक्षमता, परीक्षणक्षमता, लचीलता च सुधरति

निर्भरता-इञ्जेक्शनस्य मूल-अवधारणा

  1. विश्वसिति : वस्तुनः कार्यं पूर्णं कर्तुं अन्यस्य वस्तुनः आवश्यकता भवति, ततः पूर्वः उत्तरस्य उपरि आश्रितः भवति। यथा, OrderService वर्गः उत्पादसूचना प्राप्तुं ProductRepository वर्गे अवलम्बितुं शक्नोति ।
  2. इन्जेक्शन इति : आश्रितवस्तुं यस्य वस्तुनः आवश्यकता अस्ति तस्मै प्रसारयन्तु, तस्य स्थाने यस्य वस्तुनः आवश्यकता अस्ति तत् स्वयं आश्रितवस्तुं निर्मातुम् अददात् । कन्स्ट्रक्टर्, प्रॉपर्टी, अथवा मेथड् पैरामीटर्स् इत्येतयोः माध्यमेन इन्जेक्शन् प्राप्तुं शक्यते ।
  3. पात्रम् : वस्तुनिर्माणं निर्भरतां च प्रबन्धयति इति रूपरेखा अथवा पुस्तकालयः । पात्रस्य उत्तरदायित्वं वस्तुनां उदाहरणीकरणं, आश्रयाणां समाधानं, आश्रितवस्तूनाम् आवश्यकतावस्तुषु प्रक्षेपणं च भवति ।

आश्रयस्य इन्जेक्शनस्य प्रकाराः

कन्स्ट्रक्टर इन्जेक्शन: आश्रितं वस्तु वर्गस्य कन्स्ट्रक्टर् मार्गेण पारितं भवति ।

public class OrderService
{
    private readonly IProductRepository _productRepository;

    public OrderService(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

सम्पत्ति इन्जेक्शन: आश्रितवस्तूनि वर्गस्य सार्वजनिकगुणैः पारितानि भवन्ति।

public class OrderService
{
    public IProductRepository ProductRepository { get; set; }
}
  • 1
  • 2
  • 3
  • 4

विधि इन्जेक्शन: आश्रितं वस्तु वर्गस्य मेथड् पैरामीटर् द्वारा पारितं भवति ।

public class OrderService
{
    public void ProcessOrder(IProductRepository productRepository)
    {
        // 使用 productRepository 处理订单
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

आश्रयस्य इन्जेक्शन् किमर्थम् आवश्यकम्

निर्भरता-इञ्जेक्शन् (DI) एकः डिजाइन-प्रतिमानः अस्ति यस्य माध्यमेन वस्तुनां निर्माणं वस्तुनां मध्ये आश्रयस्य प्रबन्धनं च वस्तुनः अन्तः बाह्यपात्रे अथवा ढाञ्चे स्थानान्तरितुं शक्यते आश्रयस्य इन्जेक्शनस्य अनेकाः महत्त्वपूर्णाः कारणानि लाभाः च सन्ति : १.

  1. युग्मनं न्यूनीकरोतु : Dependency injection इत्यनेन वस्तुनः अन्तः आश्रितानां प्रबन्धनं बाह्यपात्रे स्थानान्तरितम् अस्ति, येन वस्तुनः आश्रितानां वस्तुनां निर्माणं कथं करणीयम् इति ज्ञातुं आवश्यकता नास्ति, अपितु केवलं आश्रितवस्तुनः अन्तरफलकं ज्ञातुं आवश्यकम् एतेन वस्तुनां मध्ये युग्मनं महत्त्वपूर्णतया न्यूनीकर्तुं शक्यते तथा च कोडः अधिकं मॉड्यूलरः लचीलः च भवितुम् अर्हति ।
  2. परीक्षणक्षमतायां सुधारं कुर्वन्तु : निर्भरता-इञ्जेक्शन्-इत्यनेन यूनिट्-परीक्षणं सुलभं, अधिक-कुशलं च भवति । वास्तविकनिर्भरवस्तूनाम् स्थाने नकलीवस्तूनाम् अथवा स्टब्स् इत्यस्य उपयोगेन विकासकाः वास्तविककार्यन्वयनस्य उपरि अवलम्बं विना यूनिट् परीक्षणं कर्तुं शक्नुवन्ति । एतेन परीक्षणस्य स्वातन्त्र्यं विश्वसनीयतां च सुनिश्चित्य साहाय्यं भवति ।
  3. परिपालनक्षमतायां सुधारं कुर्वन्तु : यतः निर्भरता-इञ्जेक्शन् इत्यनेन वस्तुनां मध्ये युग्मनं न्यूनीकरोति, तस्मात् कोडः अधिकं मॉड्यूलरः स्पष्टः च भवति । अनेन कोडस्य अवगमनं, परिपालनं च सुलभं भवति । यदा भवन्तः आश्रितवस्तुं परिवर्तयितुं प्रतिस्थापयितुं वा प्रवृत्ताः भवन्ति तदा भवन्तः केवलं विन्यासस्य पञ्जीकरणसूचनायाः वा परिवर्तनं कर्तुं प्रवृत्ताः सन्ति, वस्तुनः उपयोगं कुर्वन्तं कोडं परिवर्तयितुं विना ।
  4. लचीलापनं सुधारयन्तु : निर्भरता-इञ्जेक्शन्-प्रणालीं अधिकं लचीलं करोति तथा च भिन्न-भिन्न-कार्यं वा व्यवहारं वा प्राप्तुं आश्रित-वस्तूनाम् स्थाने सहजतया प्रतिस्थापयितुं शक्नोति । यथा, व्यावसायिकतर्कसङ्केतं परिवर्तनं विना विन्याससञ्चिकाभिः अथवा कोडद्वारा भिन्नानि दत्तांशकोशप्रवेशस्तरकार्यन्वयनानि स्विच् कर्तुं शक्यन्ते ।
  5. चिन्तानां पृथक्करणं प्रवर्तयन्तु : निर्भरता-इञ्जेक्शन् चिन्तानां पृथक्करणं (Separation of Concerns) प्राप्तुं साहाय्यं करोति, येन प्रत्येकं वस्तु केवलं स्वस्य उत्तरदायित्वस्य विषये एव ध्यानं दातुं आवश्यकं भवति, यत्र तस्य आश्रितानां वस्तूनाम् निर्माणं कथं करणीयम् इति चिन्ता नास्ति एतेन कोड् स्पष्टतां, परिपालनक्षमता च सुधारयितुम् साहाय्यं भवति ।
  6. डिजाइनप्रतिमानानाम् उत्तमप्रथानां च समर्थनं कुर्वन्तु : निर्भरता-इञ्जेक्शन् अनेकेषां डिजाइन-प्रतिमानानाम् उत्तम-प्रथानां च आधारः भवति, यथा नियन्त्रणस्य उल्टा (IoC), सेवा-स्थानक-प्रतिमानम् इत्यादीनां । निर्भरता-इञ्जेक्शन्-इत्यस्य उपयोगेन विकासकाः एतान् प्रतिमानान् अभ्यासान् च अधिकसुलभतया कार्यान्वितुं शक्नुवन्ति, येन कोड-गुणवत्ता, मापनीयता च सुधरति ।

निर्भरता-इञ्जेक्शनं कथं कार्यान्वितम्

अयं लेखः WPF Code address इत्यस्मिन् dependency injection इत्यस्य उपयोगं ज्ञातुं WPF Gallery परियोजनायाः उपयोगं करोति ।

https://github.com/microsoft/WPF-नमूना/blob/main/नमूनाअनुप्रयोग/WPFGallery

अस्मिन् परियोजनायां निर्भरता-इञ्जेक्शनं कार्यान्वितुं एतयोः संकुलयोः उपयोगः भवति ।

छवि-20240711100435001

प्रथमं App.xaml.cs इत्यस्य सामग्रीं पश्यन्तु:

public partial class App : Application
{

    private static readonly IHost _host = Host.CreateDefaultBuilder()
        .ConfigureServices((context, services) =>
        {
            services.AddSingleton<INavigationService, NavigationService>();
            services.AddSingleton<MainWindow>();
            services.AddSingleton<MainWindowViewModel>();
            
            services.AddTransient<DashboardPage>();
            services.AddTransient<DashboardPageViewModel>();

            services.AddTransient<ButtonPage>();
            services.AddTransient<ButtonPageViewModel>();
            services.AddTransient<CheckBoxPage>();
            services.AddTransient<CheckBoxPageViewModel>();
            services.AddTransient<ComboBoxPage>();
            services.AddTransient<ComboBoxPageViewModel>();
            services.AddTransient<RadioButtonPage>();
            services.AddTransient<RadioButtonPageViewModel>();
            services.AddTransient<SliderPage>();
            services.AddTransient<SliderPageViewModel>();
            services.AddTransient<CalendarPage>();
            services.AddTransient<CalendarPageViewModel>();
            services.AddTransient<DatePickerPage>();
            services.AddTransient<DatePickerPageViewModel>();
            services.AddTransient<TabControlPage>();
            services.AddTransient<TabControlPageViewModel>();
            services.AddTransient<ProgressBarPage>();
            services.AddTransient<ProgressBarPageViewModel>();
            services.AddTransient<MenuPage>();
            services.AddTransient<MenuPageViewModel>();
            services.AddTransient<ToolTipPage>();
            services.AddTransient<ToolTipPageViewModel>();
            services.AddTransient<CanvasPage>();
            services.AddTransient<CanvasPageViewModel>();
            services.AddTransient<ExpanderPage>();
            services.AddTransient<ExpanderPageViewModel>();
            services.AddTransient<ImagePage>();
            services.AddTransient<ImagePageViewModel>();
            services.AddTransient<DataGridPage>();
            services.AddTransient<DataGridPageViewModel>();
            services.AddTransient<ListBoxPage>();
            services.AddTransient<ListBoxPageViewModel>();
            services.AddTransient<ListViewPage>();
            services.AddTransient<ListViewPageViewModel>();
            services.AddTransient<TreeViewPage>();
            services.AddTransient<TreeViewPageViewModel>();
            services.AddTransient<LabelPage>();
            services.AddTransient<LabelPageViewModel>();
            services.AddTransient<TextBoxPage>();
            services.AddTransient<TextBoxPageViewModel>();
            services.AddTransient<TextBlockPage>();
            services.AddTransient<TextBlockPageViewModel>();
            services.AddTransient<RichTextEditPage>();
            services.AddTransient<RichTextEditPageViewModel>();
            services.AddTransient<PasswordBoxPage>();
            services.AddTransient<PasswordBoxPageViewModel>();
            services.AddTransient<ColorsPage>();
            services.AddTransient<ColorsPageViewModel>();

            services.AddTransient<LayoutPage>();
            services.AddTransient<LayoutPageViewModel>();
            services.AddTransient<AllSamplesPage>();
            services.AddTransient<AllSamplesPageViewModel>();
            services.AddTransient<BasicInputPage>();
            services.AddTransient<BasicInputPageViewModel>();
            services.AddTransient<CollectionsPage>();
            services.AddTransient<CollectionsPageViewModel>();
            services.AddTransient<MediaPage>();
            services.AddTransient<MediaPageViewModel>();
            services.AddTransient<NavigationPage>();
            services.AddTransient<NavigationPageViewModel>();
            services.AddTransient<TextPage>();
            services.AddTransient<TextPageViewModel>();
            services.AddTransient<DateAndTimePage>();
            services.AddTransient<DateAndTimePageViewModel>();
            services.AddTransient<StatusAndInfoPage>();
            services.AddTransient<StatusAndInfoPageViewModel>();
            services.AddTransient<SamplesPage>();
            services.AddTransient<SamplesPageViewModel>();
            services.AddTransient<DesignGuidancePage>();
            services.AddTransient<DesignGuidancePageViewModel>();

            services.AddTransient<UserDashboardPage>();
            services.AddTransient<UserDashboardPageViewModel>();

            services.AddTransient<TypographyPage>();
            services.AddTransient<TypographyPageViewModel>();

            services.AddSingleton<IconsPage>();
            services.AddSingleton<IconsPageViewModel>();

            services.AddSingleton<SettingsPage>();
            services.AddSingleton<SettingsPageViewModel>();

            services.AddSingleton<AboutPage>();
            services.AddSingleton<AboutPageViewModel>();
        }).Build();


    [STAThread]
    public static void Main()
    {
        _host.Start();

        App app = new();
        app.InitializeComponent();
        app.MainWindow = _host.Services.GetRequiredService<MainWindow>();
        app.MainWindow.Visibility = Visibility.Visible;
        app.Run();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114

छवि-20240711083011393

IHost इति किम् ?

C# इत्यस्मिन्, .IHost इति एकं अन्तरफलकं यत् .NET मध्ये अनुप्रयोगानाम् निर्माणाय विन्यस्तीकरणाय च उपयुज्यतेHostअवधारणा अमूर्त।IHost अन्तरफलकं अनुप्रयोगस्य आरम्भं, चालनं, प्रबन्धनं च कर्तुं आवश्यकानां सेवानां घटकानां च संग्रहं परिभाषयति । सामान्यतया ASP.NET Core अनुप्रयोगैः सह उपयुज्यते, परन्तु अन्यप्रकारस्य .NET अनुप्रयोगैः सह अपि कार्यं करोति, यथा कन्सोल् अनुप्रयोगैः अथवा WPF कार्यक्रमैः सह ।

छवि-20240711082817268

IHostअन्तरफलकं भवतिHostBuilderवर्ग कार्यान्वयनम्, यत् निर्माणं विन्यासं च प्रदातिIHostउदाहरणविधयः ।HostBuilderभवन्तं लॉगिंग्, विन्यासः, निर्भरता-इञ्जेक्शन्-पात्रम् इत्यादीनि विविधानि सेवानि योजयितुं, स्वस्य अनुप्रयोगस्य आरम्भ-विराम-व्यवहारं च विन्यस्तुं च अनुमन्यते

छवि-20240711083048854

छवि-20240711083156306

पूर्वविन्यस्तपूर्वनिर्धारितैः सह Microsoft.Extensions.Hosting.IHostBuilder उदाहरणानि निर्मातुं सुविधाविधयः प्रदाति ।

छवि-20240711083713204

एकं IHostBuilder प्रत्यागच्छति ।

छवि-20240711084145756

छवि-20240711084211035

पात्रे सेवाः योजयन्तु। एतत् क्रिया बहुवारं आह्वयितुं शक्यते तस्य परिणामाः च सञ्चिताः भवन्ति ।

configureDelegate इति पैरामीटर् इत्यस्य अर्थः Microsoft.Extensions.DependencyInjection.ISViceCollection इत्यस्य प्रतिनिधिं विन्यस्तुं भवति ।
एतत् संग्रहं System.ISViceProvider इत्यस्य निर्माणार्थं उपयुज्यते ।

प्रतिनिधिस्य कृते द्वौ पैरामीटर् प्रकारौ आवश्यकौ: HostBuilderContext तथा ​​IServiceCollection, येषां रिटर्न् मूल्यं नास्ति ।

छवि-20240711084853971

अत्र प्रतिनिधिप्रकारं पूरयति इति Lambda व्यञ्जनं पारितं भवति ।

C# इत्यस्मिन्, .() => {} लम्ब्डा-व्यञ्जनानां कृते वाक्यविन्यासः अस्ति । Lambda expressions एकः लघुः प्रतिनिधि-वेष्टकः अस्ति यः भवन्तं अनामिकं विधिं परिभाषितुं शक्नोति तथा च प्रतिनिधिषु अथवा अभिव्यक्तिवृक्षान् समर्थयति इति विधिं प्रति पैरामीटर् रूपेण पारयितुं शक्नोति

लैम्ब्डा-अभिव्यक्तयः विधि-परिभाषायाः संक्षिप्तं मार्गं प्रददति, तथा च ते विशेषतया तदा उपयोगिनो भवन्ति यदा भवद्भिः अन्य-विधिषु मेथड्-रूपेण पैरामीटर्-रूपेण पारयितुं आवश्यकता भवति ।

छवि-20240711085344696

सेवां योजयन्ते सति अत्र द्वौ जीवनचक्रौ स्तः, AddSingleton तथा AddTransient इत्येतयोः अतिरिक्तं AddScoped अपि अस्ति ।

एतानि पद्धतयः सेवायाः जीवनचक्रं परिभाषयन्ति, अर्थात् अनुप्रयोगे सेवादृष्टान्ताः कथं निर्मीयन्ते, प्रबन्ध्यन्ते च ।

AddSingleton इति

  • जीवनचक्रम्:एकलटन
  • अर्थ : सम्पूर्णे अनुप्रयोगजीवनचक्रे केवलं एकः सेवादृष्टान्तः निर्मितः भवति । कियत् अपिवारं भवन्तः पात्रात् अनुरोधं कुर्वन्ति चेदपि समानं उदाहरणं प्रत्यागमिष्यति ।
  • प्रयोज्य दृश्य: राज्यरहितसेवानां कृते उपयुक्तः, अथवा सम्पूर्णे अनुप्रयोगे साझाः संसाधनाः, यथा विन्यासाः, लॉगर् इत्यादयः ।

AddTransient इति

  • जीवनचक्रम्: क्षणिक
  • अर्थ: प्रत्येकं पात्रात् सेवा अनुरोधिता भवति तदा नूतनं उदाहरणं निर्मीयते ।
  • प्रयोज्य दृश्य: राज्ययुक्तसेवानां कृते उपयुक्तः, अथवा परिदृश्यानां कृते उपयुक्तः येषु प्रत्येकस्य अनुरोधस्य कृते नूतनदृष्टान्तस्य आवश्यकता भवति, यथा पृष्ठानि, दृश्यप्रतिरूपाः इत्यादयः ।

AddScoped इति

  • जीवनचक्रम्: व्याप्तिः
  • अर्थ : प्रत्येकं व्याप्तेः अन्तः सेवादृष्टान्ताः अद्वितीयाः सन्ति । व्याप्तयः प्रायः अनुरोधस्य जीवनचक्रेण सह सम्बद्धाः भवन्ति, उदाहरणार्थं जाल-अनुप्रयोगेषु प्रत्येकं HTTP-अनुरोधेन सह नूतनः व्याप्तिः निर्मितः भवति ।
  • प्रयोज्य दृश्य: अनुरोधव्याप्तेः अन्तः उदाहरणानि साझां कर्तुं आवश्यकानि सेवानि उपयुक्तानि, यथा दत्तांशकोशसन्दर्भाः ।

एतासां सेवानां उपयोगं कुर्वन्तु

मुख्यकार्य्ये : १.

छवि-20240711095100016

start up इति_host,उत्तीर्णः_host.Services.GetRequiredService<MainWindow>();MainWindow उदाहरणं प्राप्नुवन्तु ।

MainWindow वर्गं उदाहरणरूपेण गृहीत्वा MainWindow.xaml.cs मध्ये MainWindow इत्यस्य कन्स्ट्रक्टर् पश्यन्तु:

public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
    _serviceProvider = serviceProvider;
    ViewModel = viewModel;
    DataContext = this;
    InitializeComponent();

    Toggle_TitleButtonVisibility();

    _navigationService = navigationService;
    _navigationService.Navigating += OnNavigating;
    _navigationService.SetFrame(this.RootContentFrame);
    _navigationService.Navigate(typeof(DashboardPage));

    WindowChrome.SetWindowChrome(
        this,
        new WindowChrome
        {
            CaptionHeight = 50,
            CornerRadius = default,
            GlassFrameThickness = new Thickness(-1),
            ResizeBorderThickness = ResizeMode == ResizeMode.NoResize ? default : new Thickness(4),
            UseAeroCaptionButtons = true
        }
    );

    this.StateChanged += MainWindow_StateChanged;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

अस्मिन् विषये अप्रासंगिकं सामग्रीं निष्कास्य यथा भवति ।

public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
    _serviceProvider = serviceProvider;
    ViewModel = viewModel; 
    _navigationService = navigationService;  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

किं भवता अवलोकितं यत् भवता एतानि वस्तुनि स्वयमेव नवीनीकरणस्य आवश्यकता नास्ति?

यदि निर्भरता-इञ्जेक्शनस्य उपयोगः न भवति तर्हि एतत् एतादृशं दृश्यते ।

public MainWindow()
{
    _serviceProvider = new IServiceProvider();
    ViewModel = new MainWindowViewModel(); 
    _navigationService = new INavigationService();  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

सारांशं कुरुत

अस्मिन् लेखे प्रथमं निर्भरता-इञ्जेक्शनस्य अवधारणायाः परिचयः कृतः, ततः निर्भरता-इञ्जेक्शनस्य आवश्यकता किमर्थम् इति व्याख्यायते, अन्ते च WPF Gallery परियोजनायाः माध्यमेन WPF मध्ये निर्भरता-इञ्जेक्शनस्य उपयोगः कथं करणीयः इति ज्ञायते

refer to

1、[WPF-नमूना/नमूना अनुप्रयोग/WPFGallery at main · microsoft/WPF-नमूना (github.com)](https://github.com/microsoft/WPF-नमूना/tree/main/नमूना अनुप्रयोग/WPFGallery)