在软件开发中,依赖注入(Dependency Injection, DI)是一种设计模式,它允许开发者将组件的依赖关系从组件本身分离出来,通常通过一个容器来管理这些依赖关系。Hiro是一个静态的依赖注入容器,一旦编译和实例化,就不能修改。但有时候,需要容器返回一个已经存在的服务实例,而这个服务实例可能在容器首次编译时还不可用。例如,假设有一个实现了IFoo接口的Foo类实例,它是一个长时间运行的服务,每次请求IFoo实例时都必须返回这个实例。
在Hiro的早期版本中,可能通过以下代码将IFoo服务注册为单例:
public interface IFoo
{
// ...
}
public class Foo : IFoo
{
// ...
}
var map = new DependencyMap();
map.AddSingletonService();
var container = map.CreateContainer();
// ... 使用容器代码
上述代码的问题在于,如果Foo实例在容器实例编译之前就已经创建,那么就不能使用它。由于假设的Foo服务是一个在每个容器编译之前就已经存在的长时间运行的服务,似乎没有办法让DependencyMap返回一个现有的对象实例。直到Hiro.Functors的出现,这个问题才得以解决。
为了简单起见,假设Foo已经被实例化:
var existingFooInstance = new Foo();
定义工厂函数:
Func makeFoo = () => existingFooInstance;
var map = new DependencyMap();
map.AddService(typeof(IFoo), makeFoo);
var container = map.CreateContainer();
获取Foo服务;这里将调用makeFoo函数:
var actualFoo = container.GetInstance();
这将评估为true:
Assert.AreSame(existingFooInstance, actualFoo);
如上代码所示,Hiro.Functors库扩展了Hiro,允许开发者使用C#的原生lambda语法向任何Hiro编译的容器添加自定义工厂方法。只需调用一次额外的DependencyMap.AddService(yourServiceType, yourFunctor),就可以将Hiro从静态容器转换为动态容器,而不会牺牲速度以换取灵活性。就是这么简单。