为了能够从另一个项目中读取文件,我正在复制写代码并根据需要进行调整。
我找到了一个看起来很难看的古玩构造,但是我不知道是否还有其他方法可以处理它。
代码看起来像这样:
int type = reader.readInt32():
BaseClass p = BaseClass.Instantiate((BaseClassEnum)type);
object.Read(reader);
这段代码看起来不错,但是,但是BaseClass.Instantiate(BaseClassEnum type)方法仍有一些不足之处。
基本上,这是一个巨大的switch case语句,它根据传递的类型参数实例化基类的子类。
这里是否有避免切换情况的方法?我可以创建一个字典,在其中将BaseClassEnum映射到某种类引用,从而允许我将其称为构造函数吗?像这样:
Dictionary<int, ???> bindings = new Dictionary<int, ???>(){
{BaseClassEnum1, SubClass1},
{BaseClassEnum2, SubClass2}
}
//...
//Assuming SubClass1 has a constructor SubClass1()
BaseClass p = new bindings[BaseClassEnum1]();
//I could even create a new constructor SubClass(BinaryReader reader) and do
BaseCoass p = new bindings[BaseClassEnum1](reader);
最后,代码看起来像这样:
BaseClass p = new bindings[(BaseClassEnum)reader.ReadInt32()](reader);
答案 0 :(得分:2)
类/类型工厂(这就是您要创建的工厂)以四种基本方式之一实现。
switch语句很丑,当然也容易出错,字典也很丑,并且有自己的错误,但是更易于测试。反射通常较慢,事件订阅也较慢。
所以,没有银弹。
您所描述的内容如下:
var binding = new Dictionary<int, Func<BaseClass>>(){{BaseClassEnum1, ()=> new SubClass1()},
{BaseClassEnum2, ()=>new SubClass2()}};
var p = new bindings[BaseClassEnum1]();
在https://dotnetfiddle.net/rWwCjw的工作示例(变量名略有不同)。
我应该注意,上面的示例都得到了简化,特别是如果假设它涵盖了应用程序中所有可能的子类,则字典应该是其自己的属性/函数,以便您可以测试(通过反射)列表中显示了应用程序中的所有子类。
答案 1 :(得分:1)
如果您更改问号???到Type
,您可以使用var p = Activator.Createinstance(binding[BaseClassEnum1], reader)