类类型字典

Ser*_*rge 6 c# generics

我有一组类,每个类都可以使用外部应用程序打开不同类型的文件,并告诉该应用程序将文件打印到特定的打印机.这些类都继承了一个公共抽象类和一个接口.

internal interface IApplicationPrinter : IDisposable
{
    string ApplicationExe { get; }
    string ApplicationName { get; }
    string[] PrintableExtensions { get; }

    IApplicationPrinter CreateInstance(string Filename, string Printer);
    void Print();
    bool ExitApplicationAfterPrint { get; set; }
    bool WaitApplicationExitOnPrint { get; set; }
    System.IO.FileInfo PdfFile { get; protected set; }
}
internal abstract class ApplicationPrinter : IApplicationPrinter
{
    ...
}
internal class WordPrinter : ApplicationPrinter
{
    internal static string[] PrintableExtensions { get { return new string[]{".doc", ".docx" }; } }
    ...
}
internal class ExcelPrinter : ApplicationPrinter
{
    internal static string[] PrintableExtensions { get { return new string[]{".xls", ".xlsx" }; } }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个Dictionary可打印的文件扩展名和Type可以打印此类文件的相应类.我希望实例在字典中的类.

private static Dictionary<string, Type> FileConverters;
static Printer()
{
    FileConverters = new Dictionary<string, Type>();

    foreach (string ext in WordPrinter.PrintableExtensions)
    {
        FileConverters.Add(ext, typeof(WordPrinter));
    }

    string filename = "textfile.txt";
    string extension = filename.Substring(filename.LastIndexOf("."));

    if (FileConverters.ContainsKey(extension))
    {
        IApplicationPrinter printer = ((IApplicationPrinter)FileConverters[extension]).CreateInstance(filename, "Printer");
        printer.Print();
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法Dictionary<string, Type> FileConverters通过将其限制为实现IApplicationPrinter的值来提高类型安全性?换句话说,这样的事情是可能的:

private static Dictionary<string, T> FileConverters where T: IApplicationPrinter;
Run Code Online (Sandbox Code Playgroud)

更新:由于以下两个原因,我不想存储实例:

  1. 每个类可以处理几种不同的文件类型(参见参考资料string[] PrintableExtensions)字典将扩展名存储为键.在创建和存储同一类的多个分隔实例时没有任何实用工具.
  2. 每个打印机类都使用COM API和Office Interop来创建第三方应用程序的实例.最好是在需要时为打印作业创建每个类的新实例,并且垃圾收集器可以在之后进行清理.

Pon*_*dum 6

我的做法略有不同:

private Dictionary<String, Func<IApplicationPrinter>> _converters;

public void Initialise()
{
    foreach (string ext in WordPrinter.PrintableExtensions)
    {
        _converters.Add(ext, () => new WordPrinter());
    }
}

public IApplicationPrinter GetPrinterFor(String extension)
{
    if (_converters.ContainsKey(extension))   //case sensitive!
    {
        return _converters[extension].Invoke();
    }

    throw new PrinterNotFoundException(extension);
}
Run Code Online (Sandbox Code Playgroud)

此方法不会根据您的需要将实例存储在字典中,并且每次调用时都会为您创建一个新实例GetPrinterFor。它也具有更强的类型,因为 的返回类型Func<>必须是IApplicationPrinter


tho*_*att 3

不是直接的 - 请记住,您放入字典中的内容是Type对象,而不是实现IApplicationPrinter.

这里最好的选择可能是通过检查IApplicationPrinter是否type.GetInterface("IApplicationPrinter")返回 null 来检查添加到字典中的每种类型是否实现了。