พื้นฐานคอนเทนเนอร์ DI
ทำความเข้าใจการกลับทิศทางการควบคุม การลงทะเบียนบริการ และวิธีที่คอนเทนเนอร์ DI ของ .NET แก้ไข dependency
พื้นฐานคอนเทนเนอร์ DI เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
การฉีดการพึ่งพาคืออะไร
การฉีดการพึ่งพา (DI) คือรูปแบบการออกแบบที่คลาสได้รับสิ่งที่ต้องพึ่งพาจากแหล่งภายนอก แทนที่จะสร้างสิ่งเหล่านั้นขึ้นมาเอง
แทนที่จะเขียน var repo = new UserRepository(); ไว้ภายในคลาส คลาสจะประกาศสิ่งที่ต้องใช้ และคอนเทนเนอร์ DI จะจัดเตรียมสิ่งนั้นให้
การกลับด้านการควบคุม
DI คือการนำหลักการกลับด้านการควบคุม (IoC) มาใช้อย่างเป็นรูปธรรม กล่าวคือ การควบคุมการสร้างสิ่งที่ต้องพึ่งพาจะถูกเปลี่ยนจากคลาสที่ต้องพึ่งพาไปยังคอนเทนเนอร์ภายนอก
วิธีนี้ทำให้คลาสต่าง ๆ ทดสอบและแทนที่ได้ง่ายขึ้น
การตั้งค่าคอนเทนเนอร์ DI ของ .NET
ในแอป .NET จะกำหนดค่าคอนเทนเนอร์ DI ผ่านทาง IServiceCollection ใน Program.cs จากนั้นบริการต่าง ๆ จะได้รับการลงทะเบียนและถูกเรียกใช้งานโดยระบบขณะทำงาน
var builder = WebApplication.CreateBuilder(args);
// Register services
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<UserService>();
var app = builder.Build();
app.Run();การกำหนดอินเทอร์เฟซและการนำไปใช้งาน
DI ทำงานได้ดีที่สุดเมื่อเขียนโปรแกรมโดยยึดอินเทอร์เฟซเป็นหลัก ให้กำหนดอินเทอร์เฟซสำหรับข้อตกลงของบริการ และกำหนดคลาสจริงที่นำอินเทอร์เฟซนั้นไปใช้งาน
public interface IUserRepository
{
User? GetById(int id);
}
public class UserRepository : IUserRepository
{
public User? GetById(int id)
{
// fetch from database
return new User { Id = id, Name = "Alice" };
}
}การแก้ไขบริการผ่านคอนสตรัคเตอร์
คอนเทนเนอร์จะฉีดบริการที่ลงทะเบียนไว้เข้าไปในคอนสตรัคเตอร์โดยอัตโนมัติ คลาสเพียงประกาศอินเทอร์เฟซที่ต้องการ ก็ไม่จำเป็นต้องใช้คีย์เวิร์ด new
public class UserService
{
private readonly IUserRepository _repo;
public UserService(IUserRepository repo)
{
_repo = repo;
}
public User? FindUser(int id) => _repo.GetById(id);
}การลงทะเบียนบริการหลายรายการ
คุณสามารถลงทะเบียนบริการได้มากเท่าที่จำเป็น เมธอดส่วนขยายที่ใช้กันทั่วไปคือ AddTransient, AddScoped และ AddSingleton ซึ่งแต่ละรายการจะกำหนดอายุการใช้งานที่แตกต่างกัน
builder.Services.AddSingleton<IConfig, AppConfig>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddScoped<UserService>();การใช้ IServiceProvider โดยตรง
ในบางกรณีที่พบไม่บ่อย คุณอาจจำเป็นต้องแก้ไขบริการแบบสั่งการโดยตรง IServiceProvider ช่วยให้คุณเรียก GetRequiredService<T>() เพื่อแก้ไขบริการได้ แต่โดยทั่วไปควรใช้การฉีดผ่านคอนสตรัคเตอร์
// Anti-pattern (service locator) — use sparingly
public class ManualResolver
{
private readonly IServiceProvider _sp;
public ManualResolver(IServiceProvider sp) => _sp = sp;
public void DoWork()
{
var svc = _sp.GetRequiredService<UserService>();
svc.FindUser(1);
}
}การลงทะเบียนเจเนอริกแบบเปิด
DI ของ .NET รองรับการลงทะเบียนเจเนอริกแบบเปิด คุณสามารถลงทะเบียน IRepository<> เพียงครั้งเดียว แล้วระบบจะแก้ไขเป็น Repository<T> สำหรับชนิดเอนทิตีใดก็ได้
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
// Resolves as:
// IRepository<User> -> Repository<User>
// IRepository<Order> -> Repository<Order>การตรวจสอบความถูกต้องเมื่อเริ่มต้น
เมื่อใช้ ValidateOnStart() หรือ ValidateScopes = true คอนเทนเนอร์จะตรวจพบการลงทะเบียนที่กำหนดค่าไม่ถูกต้อง เช่น การเก็บบริการแบบ Scoped ไว้ภายใน Singleton ตั้งแต่เริ่มต้นแอป แทนที่จะรอจนเกิดขึ้นขณะทำงาน
builder.Services.AddScoped<IMyService, MyService>();
// Detect scope violations at startup
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = true;
options.ValidateOnBuild = true;
});การตกแต่งบริการ
คุณสามารถห่อหุ้มบริการด้วยตัวตกแต่งได้โดยไม่ต้องแก้ไขคลาสเดิม ให้ลงทะเบียนบริการภายในก่อน จากนั้นจึงลงทะเบียนตัวตกแต่งที่ห่อหุ้มบริการนั้น
builder.Services.AddScoped<IUserRepository, UserRepository>();
// Decorator pattern
builder.Services.Decorate<IUserRepository, CachedUserRepository>();
// Requires Scrutor NuGet packageตัวอย่างจริง: Minimal API กับ DI
ใน Minimal API บริการจะถูกฉีดเข้าไปในพารามิเตอร์ของตัวจัดการเส้นทางโดยตรง คอนเทนเนอร์จะดำเนินการแก้ไขบริการเหล่านั้นให้โดยอัตโนมัติ
app.MapGet("/users/{id}", (int id, UserService svc) =>
{
var user = svc.FindUser(id);
return user is null ? Results.NotFound() : Results.Ok(user);
});ตรวจสอบความเข้าใจ
ในคลาสส่วนใหญ่ คุณควรเลือกใช้เมธอดใดเพื่อรับสิ่งที่ต้องพึ่งพา
ทบทวน: พื้นฐานคอนเทนเนอร์ DI
ประเด็นสำคัญ:
- DI กลับทิศทางการสร้างสิ่งที่ต้องพึ่งพา โดยคอนเทนเนอร์เป็นผู้สร้างอ็อบเจ็กต์ ไม่ใช่ตัวคลาสเอง
- ลงทะเบียนบริการด้วย AddTransient / AddScoped / AddSingleton
- การฉีดผ่านคอนสตรัคเตอร์เป็นแนวทางมาตรฐานและเป็นแนวทางที่แนะนำ
- เจเนอริกแบบเปิด ตัวตกแต่ง และ ValidateOnBuild เป็นความสามารถขั้นสูงที่ทรงพลัง
คำถามที่พบบ่อย
บทเรียน “พื้นฐานคอนเทนเนอร์ DI” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พื้นฐานคอนเทนเนอร์ DI” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐานคอนเทนเนอร์ DI”
ทำความเข้าใจการกลับทิศทางการควบคุม การลงทะเบียนบริการ และวิธีที่คอนเทนเนอร์ DI ของ .NET แก้ไข dependency คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “พื้นฐานคอนเทนเนอร์ DI” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐานคอนเทนเนอร์ DI
- อายุการใช้งานบริการ: ชั่วคราว มีขอบเขต Singleton
- การฉีดผ่าน Constructor และอินเทอร์เฟซ
- รูปแบบ Factory และ Options