【发布时间】:2016-06-30 22:01:28
【问题描述】:
我在使用 .NET 反射时遇到了一个奇怪的问题。如果您知道为什么会这样,请告诉我。
要求:
我需要在实现特定接口的特定命名空间中生成每个类的实例集合。
原解决方案:
List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
t => !t.IsAbstract && t.IsClass && t.IsAssignableFrom(typeof(IReport)) && t.Namespace
== @namespace).Select(t => Activator.CreateInstance(t) as IReport).ToList();
这个原始解决方案什么也没返回,我的问题是为什么?每个类都正确实现了IReport 接口,并已在相关的命名空间中声明。这可以通过删除对IsAssignableFrom 的调用来证明:
List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
t => !t.IsAbstract && t.IsClass && t.Namespace == @namespace).Select(t =>
Activator.CreateInstance(t) as IReport).ToList();
这将准确返回我想要的类的实例,但不检查所需的接口。注意Activator.CreateInstance方法的结果被成功转换为IReport接口,所以返回的类肯定实现了。我继续解决这个问题,并设法在以下查询中提出了一种解决方法,以满足我的所有要求。
工作解决方案
List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
t => !t.IsAbstract && t.IsClass && ((TypeInfo)(t)).ImplementedInterfaces.Contains(
typeof(IReport)) && t.Namespace == @namespace).Select(t => Activator.CreateInstance(t)
as IReport).ToList();
但是,我想知道为什么IsAssignableFrom 方法没有按照它在锡...呃...或MSDN 中所说的那样做。 (我也尝试了 Stack Overflow 上其他相关问题的公认解决方案,但没有成功,所以请不要建议我关注它们。
【问题讨论】:
-
再读一遍;我想你把锡倒了。
-
@Maarten,请不要编辑我的代码以按照您喜欢的方式对其进行格式化。它是完全清晰的。
-
t.IsAssignableFrom(s)的意思是“是一个 t 类型的变量,可以从 s 类型的值赋值”。您正在向后解释它。 -
@Sheridan 您的完全可读概念可能与几乎其他所有人的完全可读概念不同 :-) 但归根结底,这是您的代码。
-
哈哈@EricLippert,谢谢...我确实把锡倒了!这是一个多么棒的网站……几秒钟内就回答了!!事实上这么快,我什至不能接受答案!
标签: c# reflection interface