C#通过反射获取不同命名空间下的类(属性和方法)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#通过反射获取不同命名空间下的类(属性和方法)相关的知识,希望对你有一定的参考价值。

怎么通过反射获取多层命名空间下的类啊,试了好多次都报错,求大神解决!!!

请注意看异常信息。未能从“当前”程序集获取“外部”程序集中拥有指定完整限定名的类型。

事实上,直接使用Type.GetType()会从当前程序集,也就是"test3"程序集中查找。

想要查找NHapi.Model.V23程序集中的类型,请在该程序集上使用GetType.

Assembly asmNHapi=Assembly.LoadFrom(.....);
Type outerType=asmNHapi.GetType(............);

如果想尽量少的改动自己的代码也成,直接在你的var classes上进行linq查询就好。

Type[] classes=Assembly.LoadFrom(...).GetTypes();
Type tt=classes.FirstOrDefault(t=>t.FullName="NHapi.Model.V23.Group.ORM_001_"+properties[i]);
if(tt!=null)
    DoSomething();

最后提醒,请勿使用Assembly.Load方法,因为该方法已被弃用,请使用LoadFrom和LoadFile来加载外部程序集。


此外,类型的完全限定名和短名并不影响类型的搜索。使用GetType时会从根命名空间开始一层一层查找的,如果各层命名空间下没有重名的类,你甚至没有使用完全限定名的必要。比如上面的代码里可以使用短名进行查找。

Type tt=classes.FirstOrDefault(t=>t.Name="ORM_001_"+properties[i]);

 

刚看到上面的回答,这里我要肯定的告诉你,不管你是用文件方式还是项目引用方式,都不可能使用Type.GetType静态方法获取另一个程序集中的类型,必须在对方的程序集上进行查找!


如果你非要使用Type.GetType静态方法获取其他程序集中的类型,可以使用其的一种重载:

public static System.Type GetType(string typeName, System.Func<AssemblyName,Assembly> assemblyResolver, System.Func<Assembly,string,bool,Type> typeResolver)

该静态方法要求你提供自己的程序集名称解析器和类型名称解析器,非特殊情况不推荐使用。该方法是为了在多个程序集中同时查找多个类型而被微软提供的。

参考技术A 如果你只给出了类的完全名称(名称空间+类型),则只能获取当前程序集,和Mscorlib中的类型。
如果类型在其它程序集,就要加上程序集名称。
参考技术B 先新建一个项目,把那个dll引用进来,然后在视图-对象浏览器里面看你想反射的对象到底是什么层次结构。追问

这些都引用进来了,层次结构大概包了三个命名空间。直接去获取类名就报错。

追答

口说无凭,把上面我说的对象浏览器相关部分截图来看。

在C#中获取命名空间中的类列表[重复]

【中文标题】在C#中获取命名空间中的类列表[重复]【英文标题】:Get list of classes in namespace in C# [duplicate] 【发布时间】:2010-12-22 13:58:19 【问题描述】:

我需要以编程方式获取给定命名空间中所有类的List。如何在 C# 中实现这一点(反射?)?

【问题讨论】:

当一个问题被标记为重复并且没有引用原始问题时,这是多么令人讨厌。 【参考方案1】:
var theList = Assembly.GetExecutingAssembly().GetTypes()
                      .Where(t => t.Namespace == "your.name.space")
                      .ToList();

【讨论】:

总是有“单行”。 ;-) 是的,你一定会喜欢单线的 :-) 这假定整个命名空间都在当前程序集中,充其量是部分解决方案。 战争,那么有什么更好的解决方案?【参考方案2】:

看看这个How to get all classes within namespace?提供的答案返回一个Type[]数组,你可以轻松修改它以返回List

【讨论】:

【参考方案3】:

没有 LINQ:

试试:

Type[] types = Assembly.GetExecutingAssembly().GetTypes();
List<Type> myTypes = new List<Type>();
foreach (Type t in types)

  if (t.Namespace=="My.Fancy.Namespace")
    myTypes.Add(t);

【讨论】:

Assembly.GetExecutingAssembly().GetTypes().ToList() 会给你你想要的列表。 是的,格雷格,虽然从技术上讲,那是使用 LINQ 扩展方法,而我的示例旨在在没有 .NET 3.5 的情况下展示这一点 clean non linq example 虽然 OP 没有说程序集已经加载,所以代码可能返回一个空集,即使列表应该很长并且名称空间可能在更多程序集中: ) 公平点,我应该刚刚创建了一个带有 Assembly 参数作为输入的方法,并将客户端调用完全留给 OP。 ;-) 更多程序集中的相同命名空间不是我的设计方式。对于基本命名空间来说很好,但我绝对不会将同一命名空间中的类型分布在多个程序集中。太恶心了。【参考方案4】:

我只能想到遍历组件中的类型以在正确的命名空间中找到它们

public List<Type> GetList()
        
            List<Type> types = new List<Type>();
            var assembly = Assembly.GetExecutingAssembly();
            foreach (var type in assembly .GetTypes())
            
                if (type.Namespace == "Namespace")
                
                    types.Add(type);
                
            
            return types;
        

【讨论】:

以上是关于C#通过反射获取不同命名空间下的类(属性和方法)的主要内容,如果未能解决你的问题,请参考以下文章

C#高级程序设计Type类

C#高级程序设计Type类

C#高阶-反射

在C#中获取命名空间中的类列表[重复]

C#反射执行方法返回List,怎么获取List

C#通过反射获取类中的方法和参数个数,反射调用方法带参数