Property違いの同じ型を複数DI設定してみる。 その1
Propertyの違う、同一Objectを複数DI設定したいだけの人生だった
IEnumerableでInjectionする
DIでper RequestでInjectionしてほしいクラス
public class PiyoService { public string TagName { get; } public PiyoService(string tagName) { TagName = tagName; } }
DI設定(ServiceDescriptorの設定)
services .AddScoped(serviceProvider => new PiyoService("Hoge")) .AddScoped(serviceProvider => new PiyoService("Fuga"));
Constructor Injection
public ProductController(ProductService productService, IEnumerable<PiyoService> piyoServices) { ProductService = productService; PiyoServices = piyoServices; }
当たり前ですがこのInjectionの方法だと、IEnumerable
尚、プロパティ違いで2つのObjectをServiceDescriptorに設定している状態で、IEnumerable
Factoryクラスを作成してInjectionする
DIでper RequestでInjectionしてほしいクラス
using Dapper; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Threading.Tasks; namespace MicroORMWrapper { public class SqlManager : IAsyncDisposable { private DbConnection DbConnection { get; set; } public bool IsOpenedConnection => DbConnection.State == ConnectionState.Open; public string ConnectionName { get; } public SqlManager(DbConnection dbConnection, string connectionName) { DbConnection = dbConnection; ConnectionName = connectionName; OpenConnection(); } public void OpenConnection() { if (IsOpenedConnection) { return; } DbConnection.Open(); } public async ValueTask CloseConnectionAsync() { if (!IsOpenedConnection) { return; } DbConnection.CloseAsync(); } public IEnumerable<TResult> Select<TResult>(string query) where TResult : class? { return DbConnection.Query<TResult>(query); } public IEnumerable<TResult> Select<TResult>(string query, object prameters) where TResult : class? { return DbConnection.Query<TResult>(query, prameters); } public IEnumerable<TResult> Select<TResult, TInclude1>(string query, Func<TResult, TInclude1, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? { return DbConnection.Query(query, includeFunc, prameters, null, true, splitOn); } public IEnumerable<TResult> Select<TResult, TInclude1, TInclude2>(string query, Func<TResult, TInclude1, TInclude2, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? where TInclude2 : class? { return DbConnection.Query(query, includeFunc, prameters, null, true, splitOn); } public Task<IEnumerable<TResult>> SelectAsync<TResult>(string query) where TResult : class? { return DbConnection.QueryAsync<TResult>(query); } public Task<IEnumerable<TResult>> SelectAsync<TResult>(string query, object prameters) where TResult : class? { return DbConnection.QueryAsync<TResult>(query, prameters); } public Task<IEnumerable<TResult>> SelectAsync<TResult, TInclude1>(string query, Func<TResult, TInclude1, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? { return DbConnection.QueryAsync(query, includeFunc, prameters, null, true, splitOn); } public Task<IEnumerable<TResult>> SelectAsync<TResult, TInclude1, TInclude2>(string query, Func<TResult, TInclude1, TInclude2, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? where TInclude2 : class? { return DbConnection.QueryAsync(query, includeFunc, prameters, null, true, splitOn); } public List<TResult> SelectAsList<TResult>(string query) where TResult : class? { return DbConnection.Query<TResult>(query).AsList(); } public List<TResult> SelectAsList<TResult>(string query, object prameters) where TResult : class? { return DbConnection.Query<TResult>(query, prameters).AsList(); } public List<TResult> SelectAsList<TResult, TInclude1>(string query, Func<TResult, TInclude1, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? { return DbConnection.Query(query, includeFunc, prameters, null, true, splitOn).AsList(); } public List<TResult> SelectAsList<TResult, TInclude1, TInclude2>(string query, Func<TResult, TInclude1, TInclude2, TResult> includeFunc, object prameters, string splitOn = "Id") where TResult : class? where TInclude1 : class? where TInclude2 : class? { return DbConnection.Query(query, includeFunc, prameters, null, true, splitOn).AsList(); } public BuiltInType GetValue<BuiltInType>(string query) { return DbConnection.ExecuteScalar<BuiltInType>(query); } public BuiltInType GetValue<BuiltInType>(string query, object prameters) { return DbConnection.ExecuteScalar<BuiltInType>(query, prameters); } public Task<BuiltInType> GetValueAsync<BuiltInType>(string query) { return DbConnection.ExecuteScalarAsync<BuiltInType>(query); } public Task<BuiltInType> GetValueAsync<BuiltInType>(string query, object prameters) { return DbConnection.ExecuteScalarAsync<BuiltInType>(query, prameters); } public int Execute(string query) { return DbConnection.Execute(query); } public int Execute(string query, object prameters) { return DbConnection.Execute(query, prameters); } public Task<int> ExecuteAsync(string query) { return DbConnection.ExecuteAsync(query); } public Task<int> ExecuteAsync(string query, object prameters) { return DbConnection.ExecuteAsync(query, prameters); } public async ValueTask DisposeAsync() { await CloseConnectionAsync(); GC.SuppressFinalize(this); } } }
InjectionしてほしいFactoryクラス
using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; namespace MicroORMWrapper.Extensions.DependencyInjection { public interface ISqlManagerFactory { SqlManager GetByName(string name); } public class SqlManagerFactory : ISqlManagerFactory { private readonly IServiceProvider _serviceProvider; public SqlManagerFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; public SqlManager GetByName(string name) { return _serviceProvider.GetServices<SqlManager>().Single(o => o.ConnectionName == name); } } }
DI設定(ServiceDescriptorの設定)
public static IServiceCollection AddSqlManagers(this IServiceCollection serviceDescriptors, IEnumerable<(string connectionName, string connectionString)> connectionSettings) { foreach (var (connectionName, connectionString) in connectionSettings) { serviceDescriptors .AddScoped<DbConnection>(serviceProvider => new SqlConnection(connectionString)) .AddScoped(serviceProvider => new SqlManager(serviceProvider.GetServices<DbConnection>().Single(o => o.ConnectionString == connectionString), connectionName)); } return serviceDescriptors .AddScoped<ISqlManagerFactory, SqlManagerFactory>(); }
Constructor Injection
public ProductRepository(ISqlManagerFactory sqlManagerFactory) { SqlManager = sqlManagerFactory.GetByName(DatabaseNameResource.KashilogDatabase); }
結果から言うと、SqlManagerFactory.GetByNameメソッド内で_serviceProvider.GetServicesを呼び出す時にSqlManagerに関連するObjectのInstanceがすべて生成されるため、IEnumerable
長くなってきたので次回に続きます。