IoC - 构造函数接受运行时值作为一个参数,另一个参数是服务。

11
我有一个 WPF 应用程序,在启动时会查找一些配置文件。
对于它找到的每个配置文件,它都会在不同的窗口中显示一些信息。
每个窗口都有一个关联的 ViewModel 对象,该对象绑定到窗口的数据上下文。
因此,针对每个配置文件创建一个新的 ViewModel。将代表配置文件数据的对象传递到视图模型的构造函数中。
但是,ViewModel 还需要其他依赖项传递到构造函数中。
代码看起来像这样(在从 app.xaml 启动的引导程序中):
foreach (WindowConfig config in ConfigManager.GetConfigs())
{
    IMyService svc = new MyService();

    //change to resolve from IoC container
    MyViewModel vm = new MyViewModel(config, svc);

    Window1 view = new Window1();

    view.DataContext = vm;

    window.show();
}

我想使用Castle IoC容器来解决这些依赖项。我知道如何为IMyService执行此操作,但是如何为从配置文件创建的特定类执行此操作?

谢谢。

2个回答

8

请始终记住,在应用程序代码中,从容器中获取内容永远不是解决方案。应用程序代码应该不知道 DI 容器正在发挥作用。

当您需要根据运行时值解析依赖项时,通用解决方案是使用抽象工厂

在您的情况下,工厂可能看起来像这样(假设您的 config 变量是字符串):

public interface IViewModelFactory
{
    IViewModel Create(string configuration);
}

现在,您可以将IViewModelFactory作为单个依赖项注入循环遍历配置文件的类中。
要实现IViewModelFactory,您可以手动执行,也可以使用Castle Windsor的Typed Factory Facility自动执行。

嗯...还不太明白。这不是在问题上增加了一层抽象吗?我仍然需要向create方法传递一个参数,但也需要从容器中解析出一个参数。你能再解释一下吗?我的工厂会是这样的吗: public interface IViewModelFactory { IViewModel Create(WindowConfig configuration, IMyService svc); - ChrisCa
此外,这一切都发生在我的引导类中。这是我第一次访问容器的地方。因此,将一个依赖项传递到其中意味着它不会被容器解析...正如您可能已经注意到的那样,我有点困惑。 - ChrisCa
3
我看到你之前已经回答过这个问题了 - 这个解释最终让我理解了...谢谢。 - ChrisCa

2

您可以通过使用带有IDictionary参数的IWindsorContainer.Resolve重载函数将参数传递给Windsor,以便在解析构造函数时使用。在此字典中,键应为参数名称,值应为要用作参数值的对象:

var arguments = new Dictionary<string,object> {{ "config", config }, { "service", svc } };
var viewModel = container.Resolve<MyViewModel>(arguments);

能否从容器中解析出IMyService的具体类型(即在Windsor XML或Fluent接口中指定),并仅通过字典传递配置参数? 也许我需要改变这个方式,使得配置通过参数注入而不是构造函数注入来传递?(虽然我更喜欢不这样做) - ChrisCa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接