首页 > 解决方案 > 使用依赖注入在运行时创建 WPF 用户控件

问题描述

我从 Mark Seemann 和 Steven van Deursen 读了一本关于依赖注入的书,我正在尝试通过用 C# 编写 WPF 应用程序来练习我学到的东西。

在我的应用程序中,我需要根据用户的操作在运行时创建自定义 UserControl。每个自定义 UserControl 自然都需要自己的 DataContext。

所以我的自定义 UserControls 可能如下所示:

class ImageComponent : UserControl
{
    public ImageComponent(object dataContext)
    {
        InitializeComponent();
        DataContext = dataContext;
    }
}

class TextComponent : UserControl
{
    public TextComponent(object dataContext)
    {
        InitializeComponent();
        DataContext = dataContext;
    }
}

当然还有视图模型。为简单起见,我省略了所有依赖项(如果有)

class ImageComponentVM : ViewModelBase
{
    // Image property...
}

class TextComponentVM : ViewModelBase
{
     // Text property...
}

现在我已经定义了 UserControls 及其视图模型,我需要在某处创建它们的实例。

我正在考虑这样的事情,这样组件生产者就不必决定它需要创建什么类型。组件生产者还将包含我再次省略的其他逻辑。不是将“类型”作为字典的键,枚举也可以做这件事。

class ComponentProducer : IComponentProducer
{
    private Dictionary<Type, Func<object>> dataContextsDictionary;
    private Dictionary<Type, Func<object, FrameworkElement>> componentDictionary;

    public ComponentProducer(Dictionary<Type, Func<object>> dataContextsDictionary,
                             Dictionary<Type, Func<object, FrameworkElement>> componentDictionary)
    {
        this.dataContextsDictionary = dataContextsDictionary;
        this.componentDictionary = componentDictionary;
    }

    public FrameworkElement Produce(..data..)
    {
        var dataContext = dataContextsDictionary[data.something.GetType()].Invoke();
        var component componentDictionary[data.something.GetType()].Invoke(dataContext);
        return component;
    }
}

在组合根中,我会有以下内容:

    var datacontextDictionary = new Dictionary<Type, Func<object>>
        {
            { typeof(Image), () => new ImageComponentVM() },
            { typeof(string), () => new TextComponentVM() }
        };
    var componentDictionary = new Dictionary<Type, Func<object, FrameworkElement>>
        {
            { typeof(Image), (dataContext) => new ImageComponent(dataContext) },
            { typeof(string), (dataContext) => new TextComponent(dataContext) }
        };
    var componentProducer = new ComponentProducer(componentDictionary);

我当前的解决方案看起来与我演示的类似。我想知道不同的(和正确的)方法,如何使用依赖注入解决这类问题。

谢谢

标签: c#design-patternsdependency-injectioninversion-of-control

解决方案


推荐阅读