はじめに
これまでデスクトップアプリ(WinForms)の開発では、MEFで開発を行ってきたが、
MEFはなくなるとのことで、新たなDIとしてMicrosoft.Extensions.DependencyInjectionを
試してみた
Microsoft.Extensions.DependencyInjection は、.NET(特に ASP.NET Core / .NET Core / .NET 6+)で使われる標準の依存性注入(DI: Dependency Injection)フレームワークです。
処理概要は以下の通り
・FormからDBアクセスクラスのDaoクラスを利用する
・FormもDaoもDependencyInjectionで生成する。
・DIで生成するクラスは[AutoRegister] という属性定義で制御する
AutoRegisterAttribute.cs
まず DI 登録を制御するための属性を作ります。
ServiceLifetime を属性で指定できるのがポイント(Transient / Scoped / Singleton)
|
1 2 3 4 5 6 7 8 9 10 11 |
using System; [AttributeUsage(AttributeTargets.Class)] public class AutoRegisterAttribute : Attribute { public ServiceLifetime Lifetime { get; } public AutoRegisterAttribute(ServiceLifetime lifetime = ServiceLifetime.Transient) { Lifetime = lifetime; } } |
UserDao.cs
Dao クラス(DBアクセス)
|
1 2 3 4 5 6 7 8 9 10 11 |
using Microsoft.Extensions.DependencyInjection; [AutoRegister(ServiceLifetime.Transient)] public class UserDao { public List GetUsers() { // 本来はDBアクセス return users; } } |
MainForm.cs
Form も DI 対象にする
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System; using System.Windows.Forms; [AutoRegister] public partial class MainForm : Form { private readonly UserDao _userDao; public MainForm(UserDao userDao) { InitializeComponent(); _userDao = userDao; } private void MainForm_Load(object sender, EventArgs e) { var name = _userDao.GetUserName(1); MessageBox.Show(name); } } |
ServiceCollectionExtensions.cs
AutoRegister を使って自動登録する拡張メソッド
|
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 |
using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using System.Reflection; public static class ServiceCollectionExtensions { public static IServiceCollection AddAutoRegisteredServices( this IServiceCollection services, params Assembly[] assemblies) { var types = assemblies .SelectMany(a => a.GetTypes()) .Where(t => t.IsClass && !t.IsAbstract) .Select(t => new { Type = t, Attribute = t.GetCustomAttribute() }) .Where(x => x.Attribute != null); foreach (var item in types) { services.Add(new ServiceDescriptor( item.Type, item.Type, item.Attribute.Lifetime)); } return services; } } |
Program.cs
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Windows.Forms; static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // DI コンテナ作成 var services = new ServiceCollection(); // ★ AutoRegister されたクラスを一括登録 services.AddAutoRegisteredServices(Assembly.GetExecutingAssembly()); using (var provider = services.BuildServiceProvider()) { // ★ Form も DI から取得 var mainForm = provider.GetRequiredService(); Application.Run(mainForm); } } } |