找到所有继承自基类(和接口)的 类 和 return 列表的更好解决方案不是 List<System.Type> 但 List<Interface>
Better Solution to find all classes which inherit from a baseclass (and interface) and return a list not List<System.Type> but List<Interface>
可能是我脑子不灵了,见树不见林...
目前我有一个名为 CheckManager
的 class,它在当前程序集中搜索一个名为 UserControlBaseCheck
的特定类型,该类型在单独的库中声明。 (这很好用)
我确实有一个类型为 SortedDictionary<IBaseCheck, UserControlBaseCheck>
的变量 AllChecks(和一个知道如何排序的自定义 IComparer
class IBaseCheck
).
此变量 AllChecks 用于填充 Stack
。堆栈然后由用户处理,一旦耗尽,它就会再次填充 AllChecks
变量中所有 classes 的新实例。而整个游戏又开始了。
目前我是这样解决的:
//declaration of my container with all checks
private static SortedDictionary<IBaseCheck, UserControlBaseCheck> AllChecks =
new SortedDictionary<IBaseCheck, UserControlBaseCheck>(new Comparer());
// this is how i call the method to find all classes which inherit from the type
FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(UserControlBaseCheck));
//this is the definition... it seems to me bit odd that I have to use the Activator
//and create an instance and cast it to the interface just to do
//what i want to do...
//is there any other / easier / better way of doing so?
public static IList<IBaseCheck> FindDerivedTypes(Assembly assembly,Type baseType)
{
//FYI: until the '.Select' I get a list of type List<System.Type>
List<IBaseCheck> o = assembly.GetTypes()
.Where(t => t != baseType && baseType.IsAssignableFrom(t))
.Select(type => Activator.CreateInstance(type) as IBaseCheck)
.ToList();
return o;
}
我觉得很奇怪,我必须先创建一个类型的实例才能 use/convert 它到一个接口。为什么我不能这样做:.Select(x=> x as IBaseCheck)
我的意思是我已经有了一个对象类型为 List<System.Type>
的列表,在我看来,我正在做的只是为了获得我的类型列表 [=19] 有点矫枉过正=] (List<IBaseCheck>
)
Why can't I just do: .Select(x=> x as IBaseCheck)
因为 x
是 System.Type
类型的实例,而不是您的 UserControlBaseCheck
类型。
了解这一点很重要,当您使用反射时,您将获得类型的 元数据。 IE。您正在获取描述您的类型的数据,而不是类型本身。 System.Type
类型就是这样一种数据。它是一个运行时对象,描述您声明的类型。 不是那些实际类型,而且绝对不是那些类型的实例。
考虑简单的代码示例:
namespace ExampleNamespace
{
class A { }
}
获取表示该类型的 System.Type
的方法有很多种:
Type type1 = Assembly.GetType("ExampleNamespace.A"),
type2 = typeof(A),
type3 = (new A()).GetType();
但请注意,在上面,所有三个变量都以 System.Type
的相同实例结束。 IE。描述该类型 A 的实例。
还请注意,在最后一个赋值中,变量 type3
正在创建 A
的新实例。 IE。您可以向实例询问有关其自身类型的信息。但返回的当然不是那个实例。这是完全不同的东西:System.Type
的实例描述了 A
.
的那个实例的类型
所以回到你的例子......
您正在使用反射来搜索特定 System.Type
对象的实例。这些实例为您提供了足够的信息来确定哪些实例实现了一些基础class(或者甚至是一个接口,如果你愿意的话)。但是由于您想要 class 的实际 实例 ,您需要明确要求一个。
正如你不能这样做:
A a = typeof(A);
你也不能这样做:
IBaseCheck baseCheck = typeof(UserControlBaseCheck);
相反,您需要这样做:
IBaseCheck baseCheck = new UserControlBaseCheck();
通过反射完成的方法(好吧,无论如何,一个方法)是调用Activator.CreateInstance()
方法。
可能是我脑子不灵了,见树不见林...
目前我有一个名为 CheckManager
的 class,它在当前程序集中搜索一个名为 UserControlBaseCheck
的特定类型,该类型在单独的库中声明。 (这很好用)
我确实有一个类型为 SortedDictionary<IBaseCheck, UserControlBaseCheck>
的变量 AllChecks(和一个知道如何排序的自定义 IComparer
class IBaseCheck
).
此变量 AllChecks 用于填充 Stack
。堆栈然后由用户处理,一旦耗尽,它就会再次填充 AllChecks
变量中所有 classes 的新实例。而整个游戏又开始了。
目前我是这样解决的:
//declaration of my container with all checks
private static SortedDictionary<IBaseCheck, UserControlBaseCheck> AllChecks =
new SortedDictionary<IBaseCheck, UserControlBaseCheck>(new Comparer());
// this is how i call the method to find all classes which inherit from the type
FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(UserControlBaseCheck));
//this is the definition... it seems to me bit odd that I have to use the Activator
//and create an instance and cast it to the interface just to do
//what i want to do...
//is there any other / easier / better way of doing so?
public static IList<IBaseCheck> FindDerivedTypes(Assembly assembly,Type baseType)
{
//FYI: until the '.Select' I get a list of type List<System.Type>
List<IBaseCheck> o = assembly.GetTypes()
.Where(t => t != baseType && baseType.IsAssignableFrom(t))
.Select(type => Activator.CreateInstance(type) as IBaseCheck)
.ToList();
return o;
}
我觉得很奇怪,我必须先创建一个类型的实例才能 use/convert 它到一个接口。为什么我不能这样做:.Select(x=> x as IBaseCheck)
我的意思是我已经有了一个对象类型为 List<System.Type>
的列表,在我看来,我正在做的只是为了获得我的类型列表 [=19] 有点矫枉过正=] (List<IBaseCheck>
)
Why can't I just do:
.Select(x=> x as IBaseCheck)
因为 x
是 System.Type
类型的实例,而不是您的 UserControlBaseCheck
类型。
了解这一点很重要,当您使用反射时,您将获得类型的 元数据。 IE。您正在获取描述您的类型的数据,而不是类型本身。 System.Type
类型就是这样一种数据。它是一个运行时对象,描述您声明的类型。 不是那些实际类型,而且绝对不是那些类型的实例。
考虑简单的代码示例:
namespace ExampleNamespace
{
class A { }
}
获取表示该类型的 System.Type
的方法有很多种:
Type type1 = Assembly.GetType("ExampleNamespace.A"),
type2 = typeof(A),
type3 = (new A()).GetType();
但请注意,在上面,所有三个变量都以 System.Type
的相同实例结束。 IE。描述该类型 A 的实例。
还请注意,在最后一个赋值中,变量 type3
正在创建 A
的新实例。 IE。您可以向实例询问有关其自身类型的信息。但返回的当然不是那个实例。这是完全不同的东西:System.Type
的实例描述了 A
.
所以回到你的例子......
您正在使用反射来搜索特定 System.Type
对象的实例。这些实例为您提供了足够的信息来确定哪些实例实现了一些基础class(或者甚至是一个接口,如果你愿意的话)。但是由于您想要 class 的实际 实例 ,您需要明确要求一个。
正如你不能这样做:
A a = typeof(A);
你也不能这样做:
IBaseCheck baseCheck = typeof(UserControlBaseCheck);
相反,您需要这样做:
IBaseCheck baseCheck = new UserControlBaseCheck();
通过反射完成的方法(好吧,无论如何,一个方法)是调用Activator.CreateInstance()
方法。