在AppDomain.CurrentDomain中获取所有用户创建的类

时间:2012-06-04 12:49:08

标签: c# reflection .net-assembly

我想循环遍历我在项目中添加的所有类

Assembly[] foo = AppDomain.CurrentDomain.GetAssemblies();

foreach(Assembly a in foo)
{                
    foreach(Type t in a.GetTypes())
    {

    }
}

这是我尝试的但我想排除.net提供的程序集,例如“mscorlib”

3 个答案:

答案 0 :(得分:9)

一个常见的解决方案是按名称过滤程序集,如果所有程序集都有一个公共前缀(如果你有一个或多或少的唯一前缀)。

var foo = AppDomain.CurrentDomain.GetAssemblies()
                                 .Where(a=>a.FullName.StartsWith("MyProject."));

如果您只对某些特定类型感兴趣,请考虑为您的班级使用attributes,或者甚至在汇编级别添加一个。

示例:

创建一个属性:

[AttributeUsage(AttributeTargets.Assembly)]
public class MyAssemblyAttribute : Attribute { }

将以下内容添加到AssemblyInfo.cs:

[assembly: MyAssemblyAttribute()]

并过滤您正在查看的程序集:

var foo = AppDomain.CurrentDomain
                   .GetAssemblies()
                   .Where(a => a.GetCustomAttributes(typeof(MyAssemblyAttribute), false).Any());

你也会发现at this question有趣。在one answer中,建议检查每个程序集的完全限定名称,但这非常繁琐,例如:

//add more .Net BCL names as necessary
var systemNames = new HashSet<string>
{
    "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    ...
};

var isSystemType = systemNames.Contains(objToTest.GetType().Assembly.FullName); 

标记程序集(按名称或属性)总是比尝试识别哪些是.Net框架的一部分更容易。

答案 1 :(得分:1)

在我的一个项目中,我需要一个用作业务对象的类列表。这些类始终是用户创建的类型,但可以在引用的程序集中。它们不实现特定的接口,也不是从特定的基类派生而且没有独特的属性。

这是我用来过滤有用类型的代码:

return
    type.IsClass && // I need classes
    !type.IsAbstract && // Must be able to instantiate the class
    !type.IsNestedPrivate && // Nested private types are not accessible
    !type.Assembly.GlobalAssemblyCache && // Excludes most of BCL and third-party classes
    type.Namespace != null && // Yes, it can be null!
    !type.Namespace.StartsWith("System.") && // EF, for instance, is not in the GAC
    !type.Namespace.StartsWith("DevExpress.") && // Exclude third party lib
    !type.Namespace.StartsWith("CySoft.Wff") && // Exclude my own lib
    !type.Namespace.EndsWith(".Migrations") && // Exclude EF migrations stuff
    !type.Namespace.EndsWith(".My") && // Excludes types from VB My.something
    !typeof(Control).IsAssignableFrom(type) && // Excludes Forms and user controls
    type.GetCustomAttribute<CompilerGeneratedAttribute>() == null && // Excl. compiler gen.
    !typeof(IControllerBase).IsAssignableFrom(type); // Specific to my project

由于我的用户类型不在GAC中!type.Assembly.GlobalAssemblyCache在排除大多数BCL(框架库)类型和某些第三方内容方面做得非常好。

这不是水密的,但我的情况很好。您很可能需要根据自己的需要进行调整。

答案 2 :(得分:0)

检查内循环中Type的以下属性。

t.GetType().Namespace == "System"
t.GetType().Namespace.StartsWith("System")
t.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"