Բովանդակություն

Ի՞նչ է Dependency injection-ը

Dependency injection-ը ծրագրավորման մեխանիզմ է, որը թույլ է տալիս սահմանել բարդ ֆունկցիոնալություն տվող դասեր (սերվիսներ), որոնք ունեն բարդ ստեղծման մեխանիզմ և օգտագործել դրանք այլ դասերում առանց դրանց ստեղծման մասին մտածելու։

Օրինակ.
Համակարգում սահմանված է TreeElementService, որը իր կոնստրուկտորում պետք է ստանա 4 պարամետր։ Ինյեկցիա կիրառելով այն հնարավոր է ստանալ այլ դասում առանց կոնստրուկտորը կանչելու։

public class MyExtention
{
  private readonly TreeElementService treeElementService;
  public MyExtention(TreeElementService treeElementService)
  {
    this.treeElementService = treeElementService;
  }
  //...
}

Բարդ ֆունկցիոնալություն տվող դասերը (սերվիսները) սահմանվում են 8X համակարգի մեջ, և կարող են օգտագործվել

  • Այլ սերվիսներ ստեղծելուց,
  • ASP.NET Core Controller-ներում API-ներ սահմանող մեթոդներ սահմանելուց,
  • 8X համակարգի նկարագրություններ ստեղծելուց (Փաստաթուղթ, Տվյալների աղբյուր…),
  • 8X համակարգի ընդլայնող դասերում (Տվյալների աղբյուրի ընդլայնում, Տպվող ձևի ընդլայնում…),
  • այլ տեղերում, որտեղ հասանելի է IServiceProvider ինտերֆեյսի օբյեկտը։

IServiceProvider ինտերֆեյսի օբյեկտը դա հատուկ «հավաքածու» է, որը կարողանում է ստեղծել 8X համակարգի միացման ժամանակ ծրագրային սահմանված սերվիս դասերը իր GetService մեթոդով։

// հիմնական GetService մեթոդ
var treeElementService1 = (TreeElementService)serviceProvider.GetService(typeof(TreeElementService));

// ընդլայնված GetService մեթոդ
var treeElementService2 = serviceProvider.GetService<TreeElementService>();

Ինյեկցիայով ստեղծվող սերվիսի օբյեկտը միակն է ընթացող աշխատանքի կոնտեքստում։ Այսինքն մի քանի անգամ ինյեկցիա անելուց կամ GetService մեթոդով ստանալուց օբյեկտը լինում է նույնը։

Ավելի մանրամասն նկարագրության համար տե՛ս

Պրոյեկտում կիրառման օրինակներ

Սերվիսում օգտագործման օրինակ

TreeElementService դասը իր կախվածությունները (IDBService, TimeStampService, TreeService և IErrorHandlingService) ստանում է կոնստրուկտորով ինյեկցիայի միջոցով: Այս սերվիսները վերագրվում են դասի ներսում նախապես հայտարարված լոկալ փոփոխականներին և օգտագործվում են դասի ներսում:

public class TreeElementService
{
    private readonly IDBService dbService;
    private readonly TimeStampService timeStampService;
    private readonly TreeService treeService;
    private readonly IErrorHandlingService errorHandlingService;

    public TreeElementService(IDBService dbService,
                              TimeStampService timeStampService,
                              TreeService treeService,
                              IErrorHandlingService errorHandlingService)
    {
        this.dbService = dbService;
        this.timeStampService = timeStampService;
        this.treeService = treeService;
        this.errorHandlingService = errorHandlingService;
    }
    ...
}

Տվյալների աղբյուրում օգտագործման օրինակ

TreeNode դասը իր կախվածությունը՝ IDBService, ստանում է կոնստրուկտորով ինյեկցիայի միջոցով, ինչպես նաև IServiceProvider, որը փոխանցում է բազային DataSource դասին: Այս դասը վերագրվում է դասի ներսում նախապես հայտարարված լոկալ փոփոխականին (dbService) և օգտագործվում է դասի ներսում:

Օրինակում օգտագործված տվյալների աղբյուրի նկարագրման ձեռնարկին ծանոթանալու համար տե՛ս:
Օրինակում օգտագործված տվյալների աղբյուրի կոդին ծանոթանալու համար տե՛ս:

[DataSource("TreeNode")]
public class TreeNode : DataSource<TreeNode.DataRow, TreeNode.Param>
{
    private readonly IDBService dbService;

    public TreeNode(IDBService dbService, IServiceProvider serviceProvider) : base(serviceProvider)
    {
        this.dbService = dbService;
        ...
    }
}

Controller-ում օգտագործման օրինակ

TreeController դասը, որը նախատեսված է ծառերի և ծառերի հանգույցներին վերաբերող Http հարցումների կատարաման համար, իր կախվածությունները (TreeService, TreeElementService) ստանում է կոնստրուկտորով ինյեկցիայի միջոցով: Այս սերվիսները վերագրվում են դասի ներսում նախապես հայտարարված լոկալ փոփոխականներին և օգտագործվում են դասի ներսում:

Հնարավոր է նաև սերվիսները ինյեկցիա անել Controller-ի action-ում՝ պարամետրի կողքը ավելացնելով FromServices ատրիբուտը։ Այս եղանակը հիմնականում օգտագործվում է երբ սերվիսը օգտագործվում է տվյալ action-ում միայն, ոչ թե Controller-ի բոլոր action-ներում։

[Produces("application/json")]
[Route("api/[controller]")]
[Authorize]
[ApiController]
public class TreeController
{
    private readonly TreeService treeService;
    private readonly TreeElementService treeElementService;

    public TreeController(TreeService treeService, TreeElementService treeElementService)
    {
        this.treeService = treeService;
        this.treeElementService = treeElementService;
    }

    [HttpGet]
    public async Task<TreeElementModel> Get([FromQuery] string treeId,
                                            [FromQuery] string key,
                                            [FromServices] IApiClientInfoService apiClientInfoService)
    {
        //...
    }

    // ...
}

Տպելու ձևանմուշի ընդլայնումում օգտագործման օրինակ

AccStateAdr_Extander տպելու ձևանմուշի ընդլայնում հանդիսացող դասը իր կախվածությունը՝ UserProxyService, ստանում է կոնստրուկտորով ինյեկցիայի միջոցով: Այս դասը վերագրվում է դասի ներսում նախապես հայտարարված լոկալ փոփոխականին (proxyService) և օգտագործվում է դասի ներսում:

Օրինակում օգտագործված տպելու ձևանմուշի ընդլայնման նկարագրման ձեռնարկին ծանոթանալու համար տե՛ս:
Օրինակում օգտագործված տպելու ձևանմուշի ընդլայնման կոդին ծանոթանալու համար տե՛ս:

[TemplateSubstitutionExtender]
public class AccStateAdr_Extander : ITemplateSubstitutionExtender
{
    private readonly UserProxyService proxyService;
     
    public AccStateAdr_Extander(UserProxyService proxyService)
    {
        this.proxyService = proxyService;
    }
    ...
}