C# 创建对象族依赖于字符串或枚举,违反了开闭原则

C# 创建对象族依赖于字符串或枚举,违反了开闭原则,c#,design-patterns,C#,Design Patterns,我正在开发一个库,将HTML文档转换为word文档。这是通过遍历HTML文档并逐个处理HTML元素来完成的。有一系列类来处理每个HTML标记 public abstract class DocxElement { public void Process(); } public class DocxTable : DocxElement { public override void Process(){} } public class DocxDiv : DocxElement {

我正在开发一个库,将HTML文档转换为word文档。这是通过遍历HTML文档并逐个处理HTML元素来完成的。有一系列类来处理每个HTML标记

public abstract class DocxElement
{
   public void Process();
}

public class DocxTable : DocxElement
{
   public override void Process(){}
}

public class DocxDiv : DocxElement
{
  public override void Process(){}
}
public class ElementFactory
{

  public DocxElement Resolve(string htmlTag)
  {
     switch(htmlTag)
     {
        case "table":
         return new DocxTable();

        case "div":
         return new DocxDiv();
     }
  }
}
上面的类负责处理它的html对应项。因此,每当我扩展库以支持一个额外的html标记时,我都会从DocxElement创建一个子类。html解析器使用工厂类在遇到html标记时生成concerate DocxElement类

public abstract class DocxElement
{
   public void Process();
}

public class DocxTable : DocxElement
{
   public override void Process(){}
}

public class DocxDiv : DocxElement
{
  public override void Process(){}
}
public class ElementFactory
{

  public DocxElement Resolve(string htmlTag)
  {
     switch(htmlTag)
     {
        case "table":
         return new DocxTable();

        case "div":
         return new DocxDiv();
     }
  }
}
现在我觉得这违反了开闭原则。我不喜欢使用反射,因为设计模式需要反射。所以我创建了一个单例字典来注册元素类

Dictionary<string, Func<DocxElement>> doc;

doc.Add("table",()=>{ new DocxTable();});
字典文档;
Add(“table”,()=>{newdocxtable();});
最后,我能够消除switch语句。当我创建一个新的子类时,仍然需要向字典中添加元素


有没有更好的方法?请给出建议。

我想说你的
字典方法很好。任何试图使此泛型的操作都将丢失静态编译时检查。如果您准备牺牲编译时检查,那么可以使用反射使代码通用

public class ElementFactory
{
    public DocxElement Resolve(string htmlTag)
    {
        var type = Type.GetType(string.Format("{0}.Docx{1}",
            typeof(ElementFactory).Namespace,
            CultureInfo.CurrentCulture.TextInfo.ToTitleCase(htmlTag)));
        return (DocxElement)Activator.CreateInstance(type);
    }
}
如何使用:

ElementFactory factory = new ElementFactory();
var table = factory.Resolve("table");//Works
var div = factory.Resolve("div");//Works
var span = factory.Resolve("span");//Explodes!!
正如您所看到的,由于几个原因,这可能导致运行时失败。找不到类型、找不到类型但没有公共无参数构造函数、找不到类型但它不派生自
多元素
,等等

因此,您最好坚持使用
字典
选项IMO