小白徒手撸构造函数注入

在上一节:手把手教你写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,SingletonScoped 你打算怎么做?

小白同学: 简单, 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); // 小白同学: 创建;
} ....
}
}

大神:我!!!!!!!!!! 我给你一刀!!!!!!!

小白同学: 啊!!!!!!!!!

由于小白同学受伤,本次节目中断,等小白同学养好伤,我们再继续

下一章 小白徒手支持 SingletonScoped 生命周期

最新文章

  1. 【学习笔记】Oracle-1.安装及配置
  2. Log4j2在WEB项目中配置
  3. Java SpringMvc+hibernate架构中,调用Oracle中的sp,传递数组参数
  4. leetcode range sum query
  5. 【Matlab&amp;Mathematica】对三维空间上的点进行椭圆拟合
  6. css实现超出文本省略号的两个方法
  7. JavaScript 原型和对象创建底层原理
  8. flex外包团队—北京动点软件:推荐一本不错的Flex书籍
  9. input实现图片或视频上传(样式+代码)
  10. fcntl获取和修改文件打开状态标志
  11. lombok 一个不错的小工具
  12. Ubuntu16.04 安装lamp环境
  13. [leetcode]239. Sliding Window Maximum滑动窗口最大值
  14. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
  15. CentOS---网络配置详解
  16. Appium robotframework-appium (ios 客户端测试)环境搭建
  17. chrome提示Adobe Flash Player过期解决
  18. [LOJ#6437][BZOJ5373]「PKUSC2018」PKUSC
  19. 自定义classLoader思考
  20. react className的2种变量写法

热门文章

  1. select的限制
  2. PIP安装Django
  3. Python_Tips
  4. 阿里巴巴已offer:Java实习五面详细面经(附解答)
  5. 划分问题(Java 动态规划)
  6. Java编发编程 - 线程池的认识(二)
  7. Linux下查询外网IP的办法。
  8. [原题复现+审计][RoarCTF 2019]Easy Calc(http协议走私、php字符串解析漏洞)
  9. 巧妙运用Camtasia制作爱豆的动感影集
  10. Jmeter(一)发送http请求