C# 从枚举类型创建类的最干净方法?

C# 从枚举类型创建类的最干净方法?,c#,enums,factory,system.reflection,C#,Enums,Factory,System.reflection,我有以下枚举和类: public enum MyEnum { MyType1, MyType2 } public abstract class MyBaseClass { public abstract MyEnum GetMyType(); } public class MySubClass : MyBaseClass { public override MyEnum GetMyType() { return MyEnum.MyType1;

我有以下枚举和类:

public enum MyEnum
{
   MyType1,
   MyType2
}

public abstract class MyBaseClass
{
   public abstract MyEnum GetMyType();
}

public class MySubClass : MyBaseClass
{
   public override MyEnum GetMyType()
   {
      return MyEnum.MyType1;
   }
}
我想基于GetMyType()创建一个MySubClass实例,但不需要将MySubClass“注册”到某种处理程序(或者这就是方法?)。我知道通过反射(对从MyBaseClass继承的类循环汇编并检查它们的MyType)很容易做到这一点,但这就是方法吗

现在我正在做一件很长的事情:

public MyBaseClass CreateMyClass(MyEnum myEnum)
{
   if(myEnum == MyEnum.MyType1)
   {
      return new MySubClass();
   }
   else if(myEnum == MyEnum.MyType2)
   {
      return new MyOtherSubClass();
   }
}
这最终会导致我忘记手动添加新类。它将在测试中被捕获,但我宁愿不必添加类,因为所有需要的信息都已经提供了


欢迎所有关于最佳方法的建议。

我希望这个例子能解决您的问题

public enum MyEnum
{
    Type1, Type2
}
public abstract class MyBaseClass
{
    public abstract MyEnum GetMyType();
}
public class MySubClass1 : MyBaseClass
{
    public override MyEnum GetMyType()
    {
        // implementation
    }
}
public class MySubClass2 : MyBaseClass
{
    public override MyEnum GetMyType()
    {
        // implementation
    }
}
因此,您有
MySubClass1
MySubClass2
作为
MyBaseClass
的子级
这是你的方法

    public MyBaseClass CreateMyClass(MyEnum myEnum)
    {
        var dict = new Dictionary<MyEnum, Type>();
        dict.Add(MyEnum.Type1, typeof(MySubClass1));
        dict.Add(MyEnum.Type2, typeof(MySubClass2));

        var type = dict.Where(x => x.Key == myEnum).Select(x => x.Value);
        var instance = Activator.CreateInstance(type.GetType());
        return (MyBaseClass)instance;
    }

您可以创建一个自定义属性来标识所需的枚举类

public class MyCustomAttribute : Attribute
{
    public MyEnum EnumType { get; set; }
}
然后是枚举和类

public enum MyEnum
{
    MyType1,
    MyType2
}
public class MyBaseClass
{

}
[MyCustomAttribute(EnumType = MyEnum.MyType1)]
public class MySubClass : MyBaseClass
{

}
[MyCustomAttribute(EnumType = MyEnum.MyType2)]
public class MyOtherClass : MyBaseClass
{

}
您可以使用
Reflection
来确定与enum相关的类

private static Dictionary<MyEnum, Type> _myEnumDictionary = new Dictionary<MyEnum, Type>();

public MyBaseClass GetEnumClass(MyEnum enumType)
{
    if (!_myEnumDictionary.ContainsKey(enumType))
    {
        var enumClass = typeof(MySubClass).Assembly
            .GetTypes()
            .FirstOrDefault(x => x.GetCustomAttributes<MyCustomAttribute>()
                .Any(k => k.EnumType == enumType));
        if (enumClass == null)
        {
            throw new Exception("There is no declared class with the enumType" + enumType);
        }
        _myEnumDictionary.Add(enumType, enumClass);
    }
    return (MyBaseClass)Activator.CreateInstance(_myEnumDictionary[enumType]);
}

此外,还可以使用静态
词典
词典集合来防止每次查找

用自定义属性(例如
[ClassType(MyEnum.MyType1)]
装饰类,并通过反射检查该属性?或者修改整个方法,为什么需要这样做?应用于类型为InstancedCodeMaster的枚举成员的自定义属性如何:在数据库上只存储枚举类型,而不存储类信息,因此需要将枚举类型转换为类。Alex,你能解释一下应用于枚举成员的自定义属性吗?泛型如何?您可以动态创建任何类型的
MyBaseClass
。抱歉,Nyerguds,这对我没有帮助,因为我仍然需要确定要实例化什么。这也会造成始终必须手动添加新类的问题。不会真正解决我的问题,只将其移到其他位置。是的,但我们必须将映射保留在
Enum
Type
的某个位置。代码是如何理解的?@Whyser:stormmave的答案看起来很简洁,但它也将映射放在了其他地方!感觉就像我在找的一样。您认为这比将属性放在枚举成员上要好吗?若放置在枚举成员上,则每次实例化类时都不需要“查找”。(性能与设计?)您仍然需要查找,但我会将值缓存在
字典中,以使其超级快速。嗯,“是的”。在本例中,我们循环程序集中的所有类,而在“my”建议中,类型直接从枚举中知道,这将导致(psuedo代码):return(MyBaseClass)Activator.CreateInstance(MyEnumType.GetAttr())
private static Dictionary<MyEnum, Type> _myEnumDictionary = new Dictionary<MyEnum, Type>();

public MyBaseClass GetEnumClass(MyEnum enumType)
{
    if (!_myEnumDictionary.ContainsKey(enumType))
    {
        var enumClass = typeof(MySubClass).Assembly
            .GetTypes()
            .FirstOrDefault(x => x.GetCustomAttributes<MyCustomAttribute>()
                .Any(k => k.EnumType == enumType));
        if (enumClass == null)
        {
            throw new Exception("There is no declared class with the enumType" + enumType);
        }
        _myEnumDictionary.Add(enumType, enumClass);
    }
    return (MyBaseClass)Activator.CreateInstance(_myEnumDictionary[enumType]);
}
var mySubClass = GetEnumClass(MyEnum.MyType1);
var myOtherClass = GetEnumClass(MyEnum.MyType2);
//There is no lookup here. It will get the Type from Dictionary directly.
var mySubClass2 = GetEnumClass(MyEnum.MyType1);