这个场景跟《手写Unity容器--极致简陋版Unity容器》不同,这里构造AndroidPhone的时候,AndroidPhone又依赖于1个IPower,因为打电话没电了需要充电。

一、条件
1、容器--工厂
2、集合
3、反射
4、特性-相当于配置

二、思路

1、RegisterType<TFrom,TTo>()把完整类型名称当作key放入数据字典,把类型当作value放入数据字典方法

2、Resolve<T>(),根据完整类型名称从字典中取出类型

3、得到类型构造函数的参数类型,创建参数类型实例

4、最后创建类型实例

三、代码实现

1、IPhone接口

namespace SimplestUnity_OneLayer
{
interface IPhone
{
void Call();
}
}

2、AndroidPhone实现

namespace SimplestUnity_OneLayer
{
public class AndroidPhone : IPhone
{
public AndroidPhone(IPad iPad)
{
Console.WriteLine("{0}构造函数", this.GetType().Name);
}
    public void Call()
{
Console.WriteLine("{0}打电话", this.GetType().Name);
}
}
}

3、IPower接口

namespace SimplestUnity_OneLayer
{
public interface IPower
{
/// <summary>
/// 充电
/// </summary>
void ChargeBattery();
}
}

4、AndroidPower实现

namespace SimplestUnity_OneLayer
{
public class AndroidPower : IPower
{
public AndroidPower()
{
Console.WriteLine("{0}构造函数", this.GetType().Name);
} /// <summary>
/// 充电
/// </summary>
public void ChargeBattery()
{
Console.WriteLine("充电中{0}", this.GetType().Name);
}
}
}

5、定义1个标记特性DavidInjectionConstructor

namespace SimplestUnity_OneLayer
{
public class DavidInjectionConstructor:Attribute
{
}
}

6、容器--接口

public interface IDavidContainer
{
void RegisterType<TFrom, TTo>(); T Resolve<T>();
}

7、容器--实现

namespace SimplestUnity_OneLayer
{
/// <summary>
/// 容器--工厂
/// </summary>
public class DaivdContainer:IDaivdContainer
{
private Dictionary<string, Type> containerDictionary = new Dictionary<string, Type>();//字典 /// <summary>
/// 注册类型
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <typeparam name="TTo"></typeparam>
public void RegisterType<TFrom, TTo>()
{
containerDictionary.Add(typeof(TFrom).FullName, typeof(TTo));
} /// <summary>
/// 获取实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Resolve<T>()
{
Type type = containerDictionary[typeof(T).FullName];
//1、得到类型的所有构造函数
ConstructorInfo[] ctorArray = type.GetConstructors(); //2、得到有标记DavidInjectionConstructor特性的构造函数,如果都没有标记特性,那么得到参数最多的构造函数
ConstructorInfo currentCtor = null; if (ctorArray.Count(c => c.IsDefined(typeof(DavidInjectionConstructor), true)) > )
{
currentCtor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DavidInjectionConstructor), true));//得到第1个标记DavidInjectionConstructor特性的构造函数
}
else
{
currentCtor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();//得到参数个数最多的构造函数
}
List<object> paraList = new List<object>(); foreach (var para in currentCtor.GetParameters())
{
//得到的参数类型是IPower,抽象无法创建实例
var paraType = para.ParameterType;
//所以根据IPower Key,得到AndroidPower类型,具体类型就可以创建实例
var targetParaType = containerDictionary[paraType.FullName];
paraList.Add(Activator.CreateInstance(targetParaType));
}
return (T)Activator.CreateInstance(type,paraList.ToArray());
}
}
}

8、客户端调用

namespace SimplestUnity_OneLayer
{
class Program
{
static void Main(string[] args)
{
DaivdContainer davidContainer = new DaivdContainer();
davidContainer.RegisterType<IPhone, AndroidPhone>();
davidContainer.RegisterType<IPower, AndroidPower>();
IPhone iphone = davidContainer.Resolve<IPhone>(); iphone.Call();
}
}
}

9、运行效果

最新文章

  1. SQLSERVER将一个文件组的数据移动到另一个文件组
  2. Base64编码
  3. day4总结
  4. 关于js的keycode13
  5. Configuring Locales
  6. JVM的基本结构
  7. Python学习 之 数据类型(邹琪鲜 milo)
  8. HashMap Hashtable ArrayList HashSet
  9. C# WinForm多线程(三)---- Control.Invoke[转]
  10. kvm 对虚拟机里面插u盘
  11. [Twisted] 部署Twisted
  12. 深入浅出Node.js (10) - 测试
  13. leetcode[85] Maximal Rectangle
  14. touch事件分发
  15. jQuery技巧大放送【转】
  16. 取出关联数组的key值和values值
  17. 201521123068 《java程序设计》 第10周学习总结
  18. webpack4.0各个击破(7)—— plugin篇
  19. C#中equal与==的区别
  20. python 数据分析3

热门文章

  1. Vue 幸运大转盘
  2. Mysql查询语句之排序查询
  3. 我的 Input框 不可能这么可爱
  4. 《程序人生》系列-害敖丙差点被开除的P0事故
  5. socket实现ftp上传下载
  6. 简单易学的机器学习算法——决策树之ID3算法
  7. block的本质
  8. C++ 入门第一篇 Hello Word
  9. 双显卡安装Ubuntu 18.04和NVIDIA驱动
  10. 分享一个Vue数组赋值的错误