Unity:通过其构造函数依赖来解决接口实现
Unity: Resolve interface implementation by its constructor dependency
我正在尝试了解 IoC 并确定它是否适合这种特定情况。我有以下代码:
public class List { ... }
public class Form { ... }
public interface IService { ... }
public class ListService : IService {
public ListService(List list) { }
}
public class FormService : IService {
public FormService(Form form) { }
}
class Program {
static void Main(string[] args) {
IUnityContainer container = new UnityContainer();
container.RegisterType<IService, ListService>(new InjectionConstructor(typeof(List)));
container.RegisterType<IService, FormService>(new InjectionConstructor(typeof(Form)));
IService formService = container.Resolve<IService>(new DependencyOverride<Form>(new Form()));
IService listService = container.Resolve<IService>(new DependencyOverride<List>(new List()));
}
}
上面的代码显然不起作用,因为 IService
的第二次注册覆盖了第一个。但目的是能够使用其构造函数依赖项解析正确的 IService
实例。我意识到这不是典型的 IoC 场景,而是混合工厂/IoC,我想知道是否可以连接 unity 以适应这种场景。
编辑结论:
实际问题比上面的例子更复杂。 ServiceDefinition 对象(List、Form)来自 WCF Web 服务。从那里,系统将构造 IService 实例和最终导致一组 WPF 视图和视图模型的其他对象链。一些依赖在构造函数中明确定义,另一些使用接口作为其构造函数参数。
我的第一个方法是结合使用命名注册和 InjectionConstructor \ ResolvedParameter。但它很快变得非常复杂。根据 Randy 的建议,我开始使用 Unity 研究汽车工厂。这是关于技术的related post。这是我生成的代码片段
public class Form { }
public class FormService : IService{
[InjectionConstructor]
public FormService(Func<string, Form> func, string name):this(func(name)) { }
public FormService(Form form) { }
}
public class FormDataViewModel {
public FormDataViewModel(FormService svc) { }
}
public interface IService { }
class Program {
static Form GetForm(string name) {
//wcf call
return new Form();
}
static void Main(string[] args) {
IUnityContainer container = new UnityContainer();
container.RegisterInstance<Func<string, Form>>(GetForm);
container.RegisterType<IService, FormService>("form");
FormDataViewModel vm = container.Resolve<FormDataViewModel>(new DependencyOverride<string>("/system/form/test"));
}
}
上面的代码在某种意义上是一种混合 factory\IoC 方法。感谢 Unity 的灵活性。纯 IoC 不适合我的很多场景。
在 Unity 中,让多个注册与一个接口关联的唯一方法(开箱即用)是使用命名注册。
在您介绍的场景中(实际场景可能更复杂),这似乎不是问题。我想你会以某种方式知道你想要什么类型的服务(表格与列表)。
如果场景更复杂,那么你几乎总能用工厂实现你想要的(问题中提到了工厂,所以它似乎很合适)。有关一些工厂示例,请参阅 Automatic Factories。
基本上,IService
的所有适用实例都可以注入工厂,并且工厂可以在运行时(并基于任何适用的标准)确定什么是 IService
的适当实例 return。您甚至可以注入 Func<IService>
而不是 IService
来延迟对象创建。
我正在尝试了解 IoC 并确定它是否适合这种特定情况。我有以下代码:
public class List { ... }
public class Form { ... }
public interface IService { ... }
public class ListService : IService {
public ListService(List list) { }
}
public class FormService : IService {
public FormService(Form form) { }
}
class Program {
static void Main(string[] args) {
IUnityContainer container = new UnityContainer();
container.RegisterType<IService, ListService>(new InjectionConstructor(typeof(List)));
container.RegisterType<IService, FormService>(new InjectionConstructor(typeof(Form)));
IService formService = container.Resolve<IService>(new DependencyOverride<Form>(new Form()));
IService listService = container.Resolve<IService>(new DependencyOverride<List>(new List()));
}
}
上面的代码显然不起作用,因为 IService
的第二次注册覆盖了第一个。但目的是能够使用其构造函数依赖项解析正确的 IService
实例。我意识到这不是典型的 IoC 场景,而是混合工厂/IoC,我想知道是否可以连接 unity 以适应这种场景。
编辑结论:
实际问题比上面的例子更复杂。 ServiceDefinition 对象(List、Form)来自 WCF Web 服务。从那里,系统将构造 IService 实例和最终导致一组 WPF 视图和视图模型的其他对象链。一些依赖在构造函数中明确定义,另一些使用接口作为其构造函数参数。
我的第一个方法是结合使用命名注册和 InjectionConstructor \ ResolvedParameter。但它很快变得非常复杂。根据 Randy 的建议,我开始使用 Unity 研究汽车工厂。这是关于技术的related post。这是我生成的代码片段
public class Form { }
public class FormService : IService{
[InjectionConstructor]
public FormService(Func<string, Form> func, string name):this(func(name)) { }
public FormService(Form form) { }
}
public class FormDataViewModel {
public FormDataViewModel(FormService svc) { }
}
public interface IService { }
class Program {
static Form GetForm(string name) {
//wcf call
return new Form();
}
static void Main(string[] args) {
IUnityContainer container = new UnityContainer();
container.RegisterInstance<Func<string, Form>>(GetForm);
container.RegisterType<IService, FormService>("form");
FormDataViewModel vm = container.Resolve<FormDataViewModel>(new DependencyOverride<string>("/system/form/test"));
}
}
上面的代码在某种意义上是一种混合 factory\IoC 方法。感谢 Unity 的灵活性。纯 IoC 不适合我的很多场景。
在 Unity 中,让多个注册与一个接口关联的唯一方法(开箱即用)是使用命名注册。
在您介绍的场景中(实际场景可能更复杂),这似乎不是问题。我想你会以某种方式知道你想要什么类型的服务(表格与列表)。
如果场景更复杂,那么你几乎总能用工厂实现你想要的(问题中提到了工厂,所以它似乎很合适)。有关一些工厂示例,请参阅 Automatic Factories。
基本上,IService
的所有适用实例都可以注入工厂,并且工厂可以在运行时(并基于任何适用的标准)确定什么是 IService
的适当实例 return。您甚至可以注入 Func<IService>
而不是 IService
来延迟对象创建。