根据字符串参数注入类型

Inject Type based on string parameter

我想让 IoC 根据参数创建类型。我还需要有关在何处存储此参数信息的指导。

我需要根据字符串文件类型制作 classes,更具体地说,基于扩展名。

我有一个简单的数据文件信息 class:

class info
{
    public string FileName { get; set; }
}

我需要 return classes 基于那个“FileName”扩展,这样我就可以呈现查看器。

我在 WPF 中使用 DataTemplates 并将类型分配给视图效果很好。我只需要根据 FileName.

分配类型

现在我只是使用静态扩展字符串数组 new[]{".pdf",".html",".jpg"}; 来确定要 return 的类型。这是完全不可持续的。

我想要一个如下所示的数据源:

Extension     Type
============= =============
.pdf          Webviewer
.html         Webviewer
.doc          Docviewer
.docx         Docviewer
.txt          Textviewer

等等

取决于您使用的 DI 容器。例如,Simple Injector 提供了基于键解决依赖关系的方法:https://simpleinjector.readthedocs.org/en/latest/howto.html#resolve-instances-by-key

这是 case 语句、数据库 table、工厂模式和 IoC 之间的灰色地带。正确的解决方案完全基于您处理的不同文件的数量。这是一个小框架,可以 "act like" 一个 Ioc 容器供您使用,并允许您在应用程序中的单个位置定义扩展 => 查看器映射。

为您的观众提供一个公共界面或基础 class:

public interface IViewer {
    void LaunchViewer(string fileName);
}

制作映射 class:

public class FileExtensionMap {
    private Dictionary<string, IViewer> maps;
    public IViewer this[string key] {
        get {
            if (!this.maps.ContainsKey(key)) {
                throw new KeyNotFoundException();
            }

            return this.maps[key];
        }
    }

    public FileExtensionMap() {
        this.maps = new Dictionary<string, IViewer>();
        this.LoadMaps();
    }

    public void LoadMaps() {
        this.maps.Add("PDF", new PdfViewer());
        this.maps.Add("DOC", new WordViewer());
    }
}

将您的 FileExtensionMap 实例定义为单例或静态 class,随您喜欢。

一个简短的例子。你要么引用你的静态,你的单例,要么将映射器作为依赖项传递给你的调用 class:

public class Example {
    FileExtensionMap map;

    public Example(FileExtensionMap map) {
        this.map = map;
    }

    public void View(FileInfo file) {
        map[file.Extension].LaunchViewer(file.Name);
    }
}

更新的映射 class 将为每次调用实例化一个新实例:

public class FileExtensionMap {
    private Dictionary<string, Func<IViewer>> maps;
    public IViewer this[string key] {
        get {
            if (!this.maps.ContainsKey(key)) {
                throw new KeyNotFoundException();
            }

            return this.maps[key].Invoke();
        }
    }

    public FileExtensionMap() {
        this.maps = new Dictionary<string, Func<IViewer>>();
        this.LoadMaps();
    }

    public void LoadMaps() {
        this.maps.Add("PDF", () => new PdfViewer());
        this.maps.Add("DOC", () => new WordViewer());
    }
}

Unity IoC 允许使用名称注册类型。该名称可以是文件扩展名。我假设所有查看器都实现了 IViewer 接口。

// Register the viewer types
var viewers = new UnityContainer();
viewers
   .RegisterType<IViewer, Webwiewer>(".jpeg")
   .RegisterType<IViewer, Docviewer>(".doc");

// Get a viewer
var viewer = viewers.Resolve<IViewer>(ext);