简体   繁体   English

Unity:通过其构造函数依赖关系解析接口实现

[英]Unity: Resolve interface implementation by its constructor dependency

I am trying to understand IoC and determine whether it is a good fit for this particular scenario. 我正在尝试了解IoC,并确定它是否适合此特定情况。 I have the following code: 我有以下代码:

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()));
    }
}

The code above obviously doesn't work because the second registration of IService overrides the first one. 上面的代码显然不起作用,因为IService的第二次注册将覆盖第一个。 But the intent is to be able to resolve the right IService instance using its constructor dependency. 但其目的是能够使用其构造函数依赖项来解析正确的IService实例。 I realized that it is not a typical IoC scenario but a hybrid factory / IoC and I want to know if unity can be wired to accommodate such scenario. 我意识到这不是典型的IoC场景,而是混合工厂/ IoC,我想知道是否可以连接统一以适应这种情况。

Edit for Conclusion: 编辑结论:
The actual problem is more complex than the example above. 实际问题比上面的示例复杂。 The ServiceDefinition objects (List, Form) come from a WCF web service. ServiceDefinition对象(List,Form)来自WCF Web服务。 From there, the system will construct the IService instance and a chain of other objects that eventually lead to a set of WPF view and view model. 从那里,系统将构造IService实例和其他对象链,这些对象最终导致一组WPF视图和视图模型。 Some dependencies are clearly defined in the constructors, others uses interfaces as its constructor parameters. 一些依赖关系在构造函数中明确定义,其他依赖关系则将接口用作其构造函数参数。

My first approach was to use Named Registration combined with InjectionConstructor \\ ResolvedParameter. 我的第一种方法是将Named Registration与InjectionConstructor \\ ResolvedParameter结合使用。 But it quickly becomes quite convoluted. 但是很快就变得很复杂。 Per Randy's suggestion, I started looking into auto factory using Unity. 根据Randy的建议,我开始使用Unity探索汽车工厂。 Here is a related post on the technique. 这是该技术的相关文章 Here is my resulting code snippets 这是我产生的代码片段

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"));
    }
}

The code above is in a sense a hybrid factory\\IoC approach. 从某种意义上讲,以上代码是工厂\\ IoC混合方法。 Thanks goodness for the flexibility of Unity. 谢天谢地,Unity的灵活性。 Pure IoC would not be suitable in many of my scenarios. 在我的许多情况下,纯IoC都不适合。

With Unity the only way (out of the box) to have more than one registration associated with an interface is to use a named registration. 使用Unity时,拥有多个与接口相关联的注册的唯一方法(即用)是使用命名注册。

In your scenario as presented (the actual scenario might be more complicated) it doesn't appear that that should be an issue. 在您呈现的场景中(实际场景可能更复杂),这似乎没有问题。 I would think you would know in some way what type of service you wanted (Form vs. List). 我想您会以某种方式知道您想要哪种类型的服务(表格还是列表)。

If the scenario is more complicated then you can almost always achieve what you want with a factory (factory is mentioned in the question so it seems to fit). 如果情况更复杂,那么您几乎总是可以通过工厂实现所需的功能(问题中提到了工厂,因此看起来很合适)。 See Automatic Factories for some factory examples. 有关一些工厂示例,请参见自动工厂

Basically, all applicable instances of IService could be injected into the factory and the factory could determine at runtime (and based on whatever criteria is applicable) what is the appropriate IService instance to return. 基本上,可以将所有适用的IService实例注入工厂,并且工厂可以在运行时(并根据适用的任何标准)确定要返回的适当IService实例是什么。 You can even inject Func<IService> instead of IService to defer object creation. 您甚至可以注入Func<IService>而不是IService来延迟对象创建。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM