Type.GetType(“ namespace.abClassName”)返回null


216

这段代码:

Type.GetType("namespace.a.b.ClassName")

返回null

我有使用:

using namespace.a.b;

更新:

该类型存在,它在不同的类库中,我需要通过字符串名称来获取它。


请参阅此stackoverflow.com/questions/441680/…,以获取有关如何获取程序集合格名称的信息。
Polyfun

Answers:


244

Type.GetType("namespace.qualified.TypeName") 仅当在mscorlib.dll或当前正在执行的程序集中找到该类型时才起作用。

如果这两种情况都不成立,则需要一个程序集限定名称

Type.GetType("namespace.qualified.TypeName, Assembly.Name")

3
类型存在,它在不同的类库中,我需要通过字符串名称获取它
Omu

25
可以使用名称--加载程序集Assembly a = Assembly.Load("SomeLibrary");,然后使用名称从程序集-加载类型,而不必使用程序集限定名称Type t = a.GetType("namespace.a.b.ClassName");
肯尼·埃维特

6
也许您想typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);节省点麻烦,最终
Felype

Felype的回应是我唯一可以得到的回应。
鲁迪·斯科金斯

将.FirstOrDefault()添加到@Felype评论
Leandro

173

您还可以获取不带程序集限定名但带有dll名称的类型,例如:

Type myClassType = Type.GetType("TypeName,DllName");

我有同样的情况,对我有用。我需要一个类型为“ DataModel.QueueObject”的对象,并且具有对“ DataModel”的引用,所以我得到的类型如下:

Type type = Type.GetType("DataModel.QueueObject,DataModel");

逗号后的第二个字符串是引用名称(dll名称)。


2
这是“技巧”还是实际的方法?我在文档-_-中找不到这个。顺便说一句,这结束了我一个星期的痛苦!谢谢
DnR 2014年

1
这是一个更干净的解决方案,因此我很乐意看看是否有任何陷阱。
cossacksman,2015年

4
根据MSDN语法,此答案中使用的形式也是完全限定的类型名称(因此,这不是技巧)。表单是NamespaceTypeName, AssemblyNameSpecwhere AssemblyNameSpec是没有任何属性的程序集的标识符。尽管这个答案基本上是一样的接受我认为有些人喜欢这个,因为它与一些“噪音”,大会性能介绍(例如摒弃VersionCulture PublicKeyToken)。幸运的是,这些属性是可选的
马丁·利弗塞奇

对于嵌套类型,您可能需要执行类似的操作AtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo '17

谢谢,它适用于App_Code文件夹。示例:Type.GetType(“ TypeName,App_Code”);
Burak KorayBalcı17年

79

尝试使用这种方法

 public static Type GetType(string typeName)
        {
            var type = Type.GetType(typeName);
            if (type != null) return type;
            foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = a.GetType(typeName);
                if (type != null)
                    return type;
            }
            return null ;
        }

这实际上对我有用。但是,我必须通过在foreach循环之前添加子字符串修饰来进行调整,因为我传入了程序集限定名称,而Assembly.GetType()仅在排除程序集信息时才有效。
科林2015年

这看起来不错,但是使用其他程序集类型的泛型又如何呢?
Demetris Leptos

由于AppDomain不受支持,因此不适用于UWP 。不确定是否有其他选择。
James M

25
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
    lock (typeCache) {
        if (!typeCache.TryGetValue(typeName, out t)) {
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
                t = a.GetType(typeName);
                if (t != null)
                    break;
            }
            typeCache[typeName] = t; // perhaps null
        }
    }
    return t != null;
}

1
这看起来不错,但是使用其他程序集类型的泛型又如何呢?
Demetris Leptos

1
@DemetrisLeptos(我知道评论很旧-但其他人可能仍然有兴趣):使用int index = typeName.IndexOf('`'); 如果(索引> 0){typeName = _typeName.Substring(0,索引+ 2); }请注意,T通用类型的会被剥离。
Bernhard Hiller

25

如果程序集是ASP.NET应用程序生成的一部分,则可以使用BuildManager类:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);

1
这是一个很棒的答案,应该在页面上方。与获得装配的合格类型名称的旧方法相比,它就像一个饰物一样工作,简直简陋。
格雷厄姆

这非常简单而且容易发现,您可以帮助我优化反射对象的性能吗?
Alok

15

如果您的班级不在当前级别,则必须提供qualifiedName,此代码显示如何获取班级的qualifiedname

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

然后您可以使用qualifiedName获得类型

Type elementType = Type.GetType(qualifiedName);

8

如果是嵌套类型,则您可能会忘记转换。到+

无论如何,typeof( T).FullName都会告诉您您应该说什么

编辑:顺便说一下,using(我确定您知道)只是在编译时对编译器的指令,因此不会对API调用的成功产生任何影响。(如果您有项目或程序集引用,则可能会产生影响-因此信息并不是没有用的,它只需要进行一些过滤...)


天啊!您知道在哪里解释“ +”语法吗?
保护者一

1
我从amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC 中学到了Protectorone ,但这有点过时了。我是否可以推荐amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/…作为一本对所有.NET开发人员都非常有用的书+包括此书?最重要的是,对于类型,CLR仅具有名称空间和名称-嵌套类型不能直接寻址。因此,一种语言(如果具有嵌套类型的概念)就可以完成所需的工作(尽管通常大多数lang使用+分隔符)
Ruben Bartelink

6

我将根据数据库中指定用户有权访问的用户控件来打开用户控件。所以我用这种方法来获取TypeName ...

Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))

因此,现在可以使用strType中返回的值来创建该对象的实例。


重新打开一个史诗般的话题...恭喜。但是,我不得不拒绝您的回答,因为TO实际上知道Typename并想从中获取类型。顺便说一句:<c> GetType(Namespace.ClassName)</ c>引用的是哪种方法,如果它的Type.GetType仅适用于当前执行程序集或mscorlib内的类型,则TO表示无此方法。这些条件适用。
HimBromBeere 2014年

2
@HimBromBeere感谢您的不赞成投票。是像您这样的人激励我发表自己的发现。我仍在学习发展,我只是在尝试帮助他人。现在您希望我回答您的问题吗?顺便说一句,我已经正确回答了这个问题。我正在创建实例的类位于另一个项目中,因此必须使用AssemblyQualified名称。因此,请在投票之前阅读其余评论。“类型存在,它在不同的类库中,我需要通过字符串名称– Omu来获得它”
Stephan

6

当我只有班级名称时,请使用以下名称:

Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();

5

由于Type.GetType(String)需要Type.AssemblyQualifiedName,因此您应该使用Assembly.CreateQualifiedName(String,String)

string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);

不需要版本,区域性和PublicKeyToken assemblyName,因此您可以使用MyAssembly.GetName()。Name。

关于Type.GetType(String)

如果类型在当前正在执行的程序集中或在Mscorlib.dll中,则提供由其名称空间限定的类型名称就足够了。


4

如果引用了程序集并且Class可见:

typeof(namespace.a.b.ClassName)

由于未找到类型,GetType返回null,对于typeof,编译器可以帮助您找出错误。


类型存在,它是在一个不同的类库,我需要通过字符串名称来得到它
雄武

4

尝试使用包含程序集信息的完整类型名称,例如:

string typeName = @"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);

当我仅使用namesspace.classname来获取不同程序集中的类的类型时,我遇到了相同的情况,并且无法正常工作。如上所示,仅当我在类型字符串中包含程序集信息时,此方法才有效。


3

确保逗号直接在全限定名之后

typeof(namespace.a.b.ClassName, AssemblyName)

因为这行不通

typeof(namespace.a.b.ClassName ,AssemblyName)

我在这上呆了几天


2

对我来说,“ +”是关键!这是我的课(是一个嵌套的课):

namespace PortalServices
{
public class PortalManagement : WebService
{
    public class Merchant
    {}
}
}

这行代码行得通:

Type type = Type.GetType("PortalServices.PortalManagement+Merchant");

1

上面的解决方案似乎是最好的给我,但它并没有为我工作,所以我做到了,如下所示:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);

Type myType = Type.GetType(typeAssemblyQualifiedName);

前提条件是您知道装配的路径。就我而言,我知道它是因为这是从另一个内部项目构建的程序集,并且包含在我们项目的bin文件夹中。

如果我正在使用Visual Studio 2013,那么我的目标.NET是4.0。这是一个ASP.NET项目,因此我通过获得了绝对路径HttpContext。但是,绝对路径不是必需的,因为MSDN上的AssemblyQualifiedNames似乎没有绝对路径


0

我作弊了。由于我要创建的类型(按名称)全部在我控制的dll中,因此我只是在程序集中的dll中放置了一个静态方法,该方法采用一个简单的名称,并从该上下文中调用type.GetType并返回结果。

最初的目的是使类型可以在配置数据中通过名称指定。此后,我更改了代码,以便用户指定要处理的格式。格式处理程序类实现一个接口,该接口确定类型是否可以解析指定的格式。然后,我使用反射来找到实现该接口的类型,并找到一种处理该格式的类型。因此,现在配置指定了格式名称,而不是特定类型。反射代码可以查看并加载相邻的dll,因此我有一个穷人的插件体系结构。


嗨,我误认了我,请修改您的回复,以便撤消。
coloboxp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.