小白徒手撸构造函数注入
在上一节:手把手教你写DI_1_DI框架有什么?
我们已经知道我们要撸哪些东西了
那么我们开始动工吧,这里呢,我们找小白同学来表演下
小白同学 :我们先定义一下我们的广告招聘纸有什么:
public abstract class ServiceDefintion // 小白同学 :我们换个名字,不叫 ServiceDescriptor ,撸也要撸出自己的标志嘛{ public abstract Type ServiceType { get; } public abstract Type ImplementationType { get; } public abstract Lifetime Lifetime { get; } }public enum Lifetime // 小白同学 :定义一下要支持的三种生命周期{ Singleton, Scoped, Transient }// 小白同学 :搞个集合存放他们public interface IServiceDefintions : IEnumerable<ServiceDefintion> { void Add(ServiceDefintion serviceDefintion); }public class ServiceDefintions : IServiceDefintions{ private readonly List<ServiceDefintion> services = new List<ServiceDefintion>(); public void Add(ServiceDefintion serviceDefintion) { if (serviceDefintion == null) { throw new ArgumentNullException(nameof(serviceDefintion)); } services.Add(serviceDefintion); } }
好,我们实现两种不同的广告类型
public class TypeServiceDefintion : ServiceDefintion // 小白同学 :这种是只提供类型的,怎么建立实例需要我们解析生成,但是对使用DI的人来说,很方便,不用管怎么去new{ public override Type ServiceType { get; } public override Type ImplementationType { get; } public override Lifetime Lifetime { get; } public TypeServiceDefintion(Type serviceType, Type implementationType, Lifetime lifetime) { ServiceType = serviceType; ImplementationType = implementationType; Lifetime = lifetime; } }public interface IImplementationFactory{ Func<INamedServiceProvider, object> ImplementationFactory { get; } }public class DelegateServiceDefintion : ServiceDefintion, IImplementationFactory // 小白同学 :这种是用户自己new对象,少数特殊情况,用户会自己写特殊逻辑,所以我们需要提供支持{ public DelegateServiceDefintion(Type serviceType, Type implementationType, Lifetime lifetime, Func<IServiceProvider, object> implementationFactory) { ServiceType = serviceType; ImplementationType = implementationType; Lifetime = lifetime; ImplementationFactory = implementationFactory; } public override Type ServiceType { get; } public override Type ImplementationType { get; } public override Lifetime Lifetime { get; } public Func<IServiceProvider, object> ImplementationFactory { get; } }
小白同学 :好了,我们有服务定义描述了,来创建IServiceProvider
吧
public class ServiceProvider : IServiceProvider{ private readonly IServiceDefintions services; public ServiceProvider(IServiceDefintions services) { this.services = services; } public object GetService(Type serviceType) { var defintion = TryGetDefintion(serviceType); // 小白同学 :查找一下服务定义 if (defintion != null) { switch (defintion.Lifetime) { case Lifetime.Singleton: return null; // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦 case Lifetime.Scoped: return null; // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦 case Lifetime.Transient: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); // 小白同学 :haha, 不用我们做,真简单 } else // 小白同学 :TypeServiceDefintion { // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦 } default: return null; } } else { return null; } } private ServiceDefintion TryGetDefintion(Type serviceType) { return services.FirstOrDefault(i => i.ServiceType == serviceType); //大神: what ? 每次都遍历一下?太low了吧? } }
小白同学 :捂脸.gif 我们居然每次都遍历,简直太笨了,赶紧改下,免得大神吐槽
public class ServiceProvider : IServiceProvider{ private readonly Dictionary<Type, ServiceDefintion> services; public ServiceProvider(IServiceDefintions services) { this.services = services.ToDictionary(i => i.ServiceType); //大神: what 1 ? 有相同的 ServiceType 怎么办? } private ServiceDefintion TryGetDefintion(Type serviceType) //大神: what 2 ? 这个方法怎么这么怪 { services.TryGetValue(serviceType, out var defintion); return defintion; } ... }
小白同学 :又被吐槽了,再改下
public class ServiceProvider : IServiceProvider{ private readonly Dictionary<Type, ServiceDefintion[]> services; //大神: 呵呵,你就这样写吧,我打赌100块你后面肯定要改 //小白同学: ...... public ServiceProvider(IServiceDefintions services) { this.services = services.GroupBy(i => i.ServiceType).ToDictionary(i => i.Key, i => i.ToArray()); } private ServiceDefintion TryGetDefintion(Type serviceType) { return services.TryGetValue(serviceType, out var defintion) ? defintion.LastOrDefault() : null; } ... }
小白同学: 好了,我们简单测试一下
[Fact]public void Test(){ var a = new ServiceDefintions(); a.Add(new DelegateServiceDefintion(typeof(TransientTest),typeof(TransientTest),Lifetime.Transient,i => this)); var service = new ServiceProvider(a); var result0 = service.GetService(typeof(TransientTest)); Assert.Same(this, result0); }// 大神: 你用this 去测瞬态?你确定this是瞬态的func 每次都会调用?// 小白同学: 我。。。。。。我改
[Fact]public void Test(){ var a = new ServiceDefintions(); a.Add(new DelegateServiceDefintion(typeof(TransientTest),typeof(TransientTest),Lifetime.Transient,i => new TransientTest())); var service = new ServiceProvider(a); var result0 = service.GetService(typeof(TransientTest)); var result1 = service.GetService(typeof(TransientTest)); Assert.NotNull(result0); Assert.NotNull(result1); Assert.NotSame(result0, result1); }
小白同学: 我们来做TypeServiceDefintion 解析支持
public class ServiceProvider : IServiceProvider{ public object GetService(Type serviceType) { ... case Lifetime.Transient: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { var d = defintion as TypeServiceDefintion; var constructor = d.ImplementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学: 反射获取构造函数 var ps = constructor.GetParameters(); var args = new object[ps.Length]; for (int j = 0; j < ps.Length; j++) { var p = ps[j]; args[j] = i.GetService(p.ParameterType); // 小白同学: 获取参数值 } return constructor.Invoke(args); // 小白同学: 创建; } .... } }
小白同学: 你看我写的不错吧
大神:呵呵,这样反射性能你考虑了吗? 泛型你考虑了吗? 还有你每次都重新生成DelegateServiceDefintion?
小白同学: 我知道反射该用IL或者表达式树处理,但观众不好看嘛
大神:呵呵,你不会写吧,你看看人家lemon大神怎么写的 - file
小白同学: 好,我下来学习。 泛型不过是再动态生成一下类型嘛,这样就行啦
public class ServiceProvider : IServiceProvider{ public object GetService(Type serviceType) { ... case Lifetime.Transient: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { var d = defintion as TypeServiceDefintion; var implementationType = serviceType.IsConstructedGenericType ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments) : d.ImplementationType; var constructor = implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学: 反射获取构造函数 ..... } .... } }
小白同学: 哦,还有缓存:
public class ServiceProvider : IServiceProvider{ private readonly Dictionary<Type, ConstructorInfo> cache = new Dictionary<Type, ConstructorInfo>(); public object GetService(Type serviceType) { ... case Lifetime.Transient: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { ConstructorInfo constructor = null; if(cache.ContainsKey(serviceType)) { constructor = cache[serviceType]; } else { var d = defintion as TypeServiceDefintion; var implementationType = serviceType.IsConstructedGenericType ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments) : d.ImplementationType; constructor = cache[serviceType] = implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学: 反射获取构造函数 } .... } .... } }
大神: .......我想自闭..... 你都不考虑多线程吗?
小白同学: !!! 我,我,我,我换成它 ConcurrentDictionary<Type, ConstructorInfo> cache
大神:算你NB,Singleton
和 Scoped
你打算怎么做?
小白同学: 简单, copy 一下
public class ServiceProvider : IServiceProvider{ private readonly ConcurrentDictionary<Type, ConstructorInfo> cache = new ConcurrentDictionary<Type, ConstructorInfo>(); public object GetService(Type serviceType) { case Lifetime.Singleton: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => { var d = defintion as TypeServiceDefintion; var implementationType = serviceType.IsConstructedGenericType ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments) : d.ImplementationType; return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); }); ar ps = constructor.GetParameters(); var args = new object[ps.Length]; for (int j = 0; j < ps.Length; j++) { var p = ps[j]; args[j] = i.GetService(p.ParameterType); // 小白同学: 获取参数值 } return constructor.Invoke(args); // 小白同学: 创建; } case Lifetime.Scoped: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => { var d = defintion as TypeServiceDefintion; var implementationType = serviceType.IsConstructedGenericType ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments) : d.ImplementationType; return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); }); ar ps = constructor.GetParameters(); var args = new object[ps.Length]; for (int j = 0; j < ps.Length; j++) { var p = ps[j]; args[j] = i.GetService(p.ParameterType); // 小白同学: 获取参数值 } return constructor.Invoke(args); // 小白同学: 创建; } case Lifetime.Transient: if(defintion is DelegateServiceDefintion defi) { return defi.ImplementationFactory(this); } else { ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => { var d = defintion as TypeServiceDefintion; var implementationType = serviceType.IsConstructedGenericType ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments) : d.ImplementationType; return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); }); ar ps = constructor.GetParameters(); var args = new object[ps.Length]; for (int j = 0; j < ps.Length; j++) { var p = ps[j]; args[j] = i.GetService(p.ParameterType); // 小白同学: 获取参数值 } return constructor.Invoke(args); // 小白同学: 创建; } .... } }
大神:我!!!!!!!!!! 我给你一刀!!!!!!!
小白同学: 啊!!!!!!!!!
由于小白同学受伤,本次节目中断,等小白同学养好伤,我们再继续