(エッセンス)2020年6月27日C#クラスライブラリIServiceCollection(拡張方法)


using AutoMapper; using Castle.DynamicProxy; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Core.Util { /// /// /// public static partial class Extention { private static readonly ProxyGenerator _generator = new ProxyGenerator(); /// /// AutoMapper MapAttribute /// /// /// public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> configure = null) { List<(Type from, Type[] targets)> maps = new List<(Type from, Type[] targets)>(); maps.AddRange(GlobalData.AllFxTypes.Where(x => x.GetCustomAttribute<MapAttribute>() != null) .Select(x => (x, x.GetCustomAttribute<MapAttribute>().TargetTypes))); var configuration = new MapperConfiguration(cfg => { maps.ForEach(aMap => { aMap.targets.ToList().ForEach(aTarget => { cfg.CreateMap(aMap.from, aTarget).IgnoreAllNonExisting(aMap.from, aTarget).ReverseMap(); }); }); cfg.AddMaps(GlobalData.AllFxAssemblies); // configure?.Invoke(cfg); }); #if DEBUG // Debug configuration.AssertConfigurationIsValid(); #endif services.AddSingleton(configuration.CreateMapper()); return services; } /// /// ITransientDependency,IScopeDependency ISingletonDependency /// /// /// public static IServiceCollection AddFxServices(this IServiceCollection services) { Dictionary<Type, ServiceLifetime> lifeTimeMap = new Dictionary<Type, ServiceLifetime> { { typeof(ITransientDependency), ServiceLifetime.Transient}, { typeof(IScopedDependency),ServiceLifetime.Scoped}, { typeof(ISingletonDependency),ServiceLifetime.Singleton} }; GlobalData.AllFxTypes.ForEach(aType => { lifeTimeMap.ToList().ForEach(aMap => { var theDependency = aMap.Key; if (theDependency.IsAssignableFrom(aType) && theDependency != aType && !aType.IsAbstract && aType.IsClass) { // services.Add(new ServiceDescriptor(aType, aType, aMap.Value)); var interfaces = GlobalData.AllFxTypes.Where(x => x.IsAssignableFrom(aType) && x.IsInterface && x != theDependency).ToList(); // if (interfaces.Count > 0) { interfaces.ForEach(aInterface => { // AOP services.Add(new ServiceDescriptor(aInterface, serviceProvider => { CastleInterceptor castleInterceptor = new CastleInterceptor(serviceProvider); return _generator.CreateInterfaceProxyWithTarget(aInterface, serviceProvider.GetService(aType), castleInterceptor); }, aMap.Value)); }); } // else { services.Add(new ServiceDescriptor(aType, aType, aMap.Value)); } } }); }); return services; } /// /// 。 /// /// /// /// /// public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression, Type from, Type to) { var flags = BindingFlags.Public | BindingFlags.Instance; to.GetProperties(flags).Where(x => from.GetProperty(x.Name, flags) == null).ForEach(aProperty => { expression.ForMember(aProperty.Name, opt => opt.Ignore()); }); return expression; } /// /// 。 /// /// /// /// /// public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) { Type from = typeof(TSource); Type to = typeof(TDestination); var flags = BindingFlags.Public | BindingFlags.Instance; to.GetProperties(flags).Where(x => from.GetProperty(x.Name, flags) == null).ForEach(aProperty => { expression.ForMember(aProperty.Name, opt => opt.Ignore()); }); return expression; } } }
関連GlobalDataグローバル遍歴プログラムセットクラスusing System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; namespace Core.Util { public static class GlobalData { static GlobalData() { string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); AllFxAssemblies = Directory.GetFiles(rootPath, "*.dll") .Where(x => new FileInfo(x).Name.Contains(FXASSEMBLY_PATTERN)) .Select(x => Assembly.LoadFrom(x)) .Where(x => !x.IsDynamic) .ToList(); AllFxAssemblies.ForEach(aAssembly => { try { AllFxTypes.AddRange(aAssembly.GetTypes()); } catch { } }); } /// /// /// public const string FXASSEMBLY_PATTERN = "Core"; /// /// /// public static readonly List<Assembly> AllFxAssemblies; /// /// /// public static readonly List<Type> AllFxTypes = new List<Type>(); /// /// UserIId /// public const string ADMINID = "Admin"; } }