เหตุใดจึงลงทะเบียนบริการซ้ำซ้อนเมื่อใช้ฟังก์ชันจากโรงงาน

ฉันกำลังอ่านหนังสือที่แสดงให้เห็นว่า Dependency Injection ทำงานอย่างไรเมื่อใช้ฟังก์ชันโรงงาน โค้ดด้านล่างคือ:

//MemoryRepository implements IRepository

public class Startup
{
    private IHostingEnvironment env;

    public Startup(IHostingEnvironment hostEnv) => env = hostEnv;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IRepository>(provider =>
        {
            if (env.IsDevelopment())
            {
                var x = provider.GetService<MemoryRepository>();
                return x;
            }
            else
            {
                return new XXX();  //return sth else;
            }
        });
        services.AddTransient<MemoryRepository>();
        ...//register other components which are dependencies of MemoryRepository
        services.AddMvc();
    }
    ...
}

ฉันไม่รู้ว่าทำไม services.AddTransient<MemoryRepository>(); ถึงจำเป็น?

เนื่องจาก services.AddTransient<IRepository>{...} กำหนดขอบเขต "ชั่วคราว" ไว้แล้ว ซึ่งหมายความว่า "ทุกครั้งที่จำเป็นต้องใช้ IRepository จะมีการจัดหาออบเจ็กต์ MemoryRepository ใหม่ (หากเป็นสภาพแวดล้อมการพัฒนา)" ดังนั้นทุกอย่างจะได้รับการตั้งค่า การขึ้นต่อกันอื่น ๆ ของ MemoryRepository จะถูกจัดการ โดยการลงทะเบียนดังต่อไปนี้

Q1-แล้วทำไมเราถึงยังต้องมี services.AddTransient<MemoryRepository>(); อีกครั้ง? ถ้าฉันแสดงความคิดเห็น แอปพลิเคชันไม่สามารถทำงานได้ ดังนั้นจึงจำเป็นต้องใช้คำสั่งนี้ ฉันไม่รู้ว่าทำไม

Q2- ถ้าฉันแก้ไข configurationServices เป็น:

public void ConfigureServices(IServiceCollection services)
{
   services.AddTransient<IRepository, MemoryRepository>();
   ...
}

แอปพลิเคชันทำงานได้สำเร็จ แล้วทำไมในกรณีนี้ ฉันไม่จำเป็นต้องเพิ่ม services.AddTransient<MemoryRepository>(); เป็น:

public void ConfigureServices(IServiceCollection services)
{
   services.AddTransient<IRepository, MemoryRepository>();
   services.AddTransient<MemoryRepository>();
   ...
}

person Community    schedule 01.08.2019    source แหล่งที่มา


คำตอบ (1)


อันแรก

services.AddTransient<IRepository>(...

บอกผู้ให้บริการว่าต้องทำอย่างไรเมื่อถูกขอให้แก้ไข IRepository

อันที่สอง

services.AddTransient<MemoryRepository>();

บอกผู้ให้บริการว่าต้องทำอย่างไรเมื่อถูกขอให้แก้ไข MemoryRepository

ในทางเทคนิคแล้วคุณไม่ได้ลงทะเบียน "สองเท่า"

แล้วทำไมเรายังต้องมี services.AddTransient<MemoryRepository>()

แล้วเมื่อไร.

provider.GetService<MemoryRepository>();

ถูกเรียกใช้ในตัวแทนโรงงาน ผู้ให้บริการรู้วิธีแก้ไขเพื่อให้เป็นไปตามสภาพแวดล้อมการพัฒนา

โดยพื้นฐานแล้วตัวอย่างโค้ดจะแสดงวิธีการพึ่งพาแบบมีเงื่อนไข ซึ่งฉันคิดว่าคุณเข้าใจแล้ว

Q2

ในสถานการณ์ที่สอง ไม่จำเป็นต้องมีการลงทะเบียนครั้งที่สอง

services.AddTransient<MemoryRepository>();

เพราะในกรณีนั้น การใช้งานเพียงครั้งเดียวคือทั้งหมดที่จำเป็น เว้นแต่มีความจำเป็นอย่างชัดเจนในการใช้ MemoryRepository เป็นการพึ่งพาแบบฉีด

person Nkosi    schedule 01.08.2019
comment
ฉันแก้ไขโพสต์ของฉัน คุณช่วยดูไตรมาสที่ 2 ได้ไหม ตามสิ่งที่คุณพูด ฉันจำเป็นต้องมี services.AddTransient<MemoryRepository>() แต่ฉันไม่มีและแอปพลิเคชันยังคงทำงานได้สำเร็จ - person ; 01.08.2019
comment
ทำไม นั่นไม่ใช่ว่า services.AddTransient<IRepository, MemoryRepository>(); หมายความว่าเมื่อถูกถาม 'IRepository' ให้จัดเตรียมวัตถุ MemoryRepository ใหม่ ไม่ใช่ว่าผู้ให้บริการยังจำเป็นต้องได้รับคำแนะนำว่าต้องทำอย่างไรเมื่อถูกขอให้แก้ไข MemoryRepository - person ; 01.08.2019
comment
เฉพาะในกรณีที่คุณต้องการใช้ MemoryRepository เป็นการพึ่งพาแบบฉีดอย่างชัดเจนเท่านั้น - person Nkosi; 01.08.2019
comment
คุณหมายถึง services.AddTransient<XXX, YYY>(); เป็นฟังก์ชัน wrapper สำหรับ services.AddTransient<XXX>(provider =>... หรือไม่ asp.net core ทำสิ่งต่าง ๆ เบื้องหลังหรือไม่ - person ; 01.08.2019
comment
ในทางหนึ่งใช่ นั่นอาจเป็นวิธีการมอง - person Nkosi; 01.08.2019