从枚举类型创建 class 的最简洁方法?
Cleanest way to create class from enum type?
我有以下枚举和 类:
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 实例,但不需要 "register" MySubClass 到某种处理程序(或者这是要走的路吗?)。我知道这可能很容易通过反射来完成(通过 Assembly for 类 继承自 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
}
}
因此,您的 MyBaseClass
中有 MySubClass1
和 MySubClass2
作为 child。
这是你的方法。
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;
}
让我简单地解释一下。
我们只是在 Enum
和 Type
之间的 Dictionary
中创建一个映射。
根据我们在参数中得到的 Enum
,Activator
创建从映射中找到的类型的实例。
这里唯一的问题是,如果我们在 dict
字典中放入 MyBaseClass
的 sub class 以外的任何类型,它将抛出运行时异常。
----------------编辑----------------
如果你想完全避免映射,那么你可以将类型作为string
函数的参数传递,并实现如下
ObjectType instance =
(ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace." + argType);
您可以创建自定义属性来标识所需的枚举 class。
public class MyCustomAttribute : Attribute
{
public MyEnum EnumType { get; set; }
}
然后是枚举和 classes;
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
来确定与枚举相关的 class。
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]);
}
最后,你可以像这样获取相关的实例class;
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);
此外,您可以使用静态 Dictionary<MyEnum, Type>
字典集合来防止每次查找。
我有以下枚举和 类:
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 实例,但不需要 "register" MySubClass 到某种处理程序(或者这是要走的路吗?)。我知道这可能很容易通过反射来完成(通过 Assembly for 类 继承自 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
}
}
因此,您的 MyBaseClass
中有 MySubClass1
和 MySubClass2
作为 child。
这是你的方法。
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;
}
让我简单地解释一下。
我们只是在 Enum
和 Type
之间的 Dictionary
中创建一个映射。
根据我们在参数中得到的 Enum
,Activator
创建从映射中找到的类型的实例。
这里唯一的问题是,如果我们在 dict
字典中放入 MyBaseClass
的 sub class 以外的任何类型,它将抛出运行时异常。
----------------编辑----------------
如果你想完全避免映射,那么你可以将类型作为string
函数的参数传递,并实现如下
ObjectType instance =
(ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace." + argType);
您可以创建自定义属性来标识所需的枚举 class。
public class MyCustomAttribute : Attribute
{
public MyEnum EnumType { get; set; }
}
然后是枚举和 classes;
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
来确定与枚举相关的 class。
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]);
}
最后,你可以像这样获取相关的实例class;
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);
此外,您可以使用静态 Dictionary<MyEnum, Type>
字典集合来防止每次查找。