根据标识符创建类

时间:2016-05-05 22:27:41

标签: c# class oop

现在我有以下功能,对我来说并不是很好看:

string input = "??";
Letter output = null;

switch(input[0])
{
    case LetterA.Id: // = 'A'
        output = new LetterA();
        break;

    case LetterB.Id: // = 'B'
        output = new LetterB();
        break;

    case LetterC.Id: // = 'C'
        output = new LetterC();
        break;

    // ...
}

if (output == null)
    throw new Exception();

output.Parse(input);

return output;

是否有更好/更短的方法来解决此问题并基于标识符创建类?

2 个答案:

答案 0 :(得分:0)

你可以使用反射。以下假设LetterLetterALetterB等都存在于同一个程序集中。

var letterType = typeof(Letter).Assembly.GetTypes()
    .Where(t => t.Name == "Letter" + input[0]);
var output = Activator.CreateInstance(letterType) as Letter;

请注意,如果无法找到类型或在实例化后无法转换为Letter,则上面应添加一些错误检查。

答案 1 :(得分:0)

你得到的东西会起作用,而且并不少见。

另一种选择是创建一个字典,将Id字符串映射到一个委托,该委托返回一个Letter或字典,将Id映射到一个派生自Letter的对象,从中可以制作克隆(该选择可能取决于不同派生的Letter类是否具有不同的构造参数。)

//example of second

Dictionary<string, Letter> PrototypeLetters = new Dictionary<string, Letter>();

//...
output = PrototypeLetters[input]->MakeClone();
//where make clone is virtual in Letter returning a Letter (of derived type as Letter)
//still need to handle case where input is not found

在缺点方面,您必须构建该映射,如果您需要改变行为,则在运行时构建它会更灵活,但这包括引入错误的灵活性,并使单元测试变得不那么容易。

在正面,从Id获取信件的代码不必知道每个派生的Letter类型。

您是否认为该选项更好取决于您比较选项的标准。