【问题标题】:Type.GetType("namespace.a.b.ClassName") returns nullType.GetType("namespace.a.b.ClassName") 返回 null
【发布时间】:2019-11-09 01:14:28
【问题描述】:

这段代码:

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

返回null。

我在使用中:

using namespace.a.b;

更新:

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

【问题讨论】:

标签: c# reflection


【解决方案1】:

试试这个方法。

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() 仅在排除程序集信息时才有效。
  • 不适用于 UWP,因为不支持 AppDomain。不确定任何替代方案。
【解决方案2】:

由于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);

assemblyName 不需要版本、文化和 PublicKeyToken,这就是您可以使用 MyAssembly.GetName().Name 的原因。

关于Type.GetType(String):

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

【讨论】:

    【解决方案3】:

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

    如果这些都不成立,您将需要assembly-qualified name:

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

    【讨论】:

    • 类型存在,在不同的类库中,需要通过字符串名获取
    • 您可以按名称加载程序集——Assembly a = Assembly.Load("SomeLibrary");——而不是使用程序集限定名称——然后从程序集中按名称加载类型——Type t = a.GetType("namespace.a.b.ClassName");。
    • 也许你可以喜欢typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName); 最终可能会省去一些麻烦
    • 使用这种方法必须指定namespace.qualified.TypeName 而不仅仅是TypeName 是否正确?
    • 如果 Type 来自服务器生成的 wsdl 怎么办?这对我不起作用。你知道为什么它不工作吗?谢谢
    【解决方案4】:

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

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

    这行代码有效:

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

    【讨论】:

      【解决方案5】:

      当我只有类名时,我使用这个:

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

      【讨论】:

        【解决方案6】:

        确保逗号直接位于完全限定名称之后

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

        因为这行不通

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

        我在这个问题上被难住了几天

        【讨论】:

          【解决方案7】:

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

          string qualifiedName = typeof(YourClass).AssemblyQualifiedName;
          

          然后你可以用qualifiedName获取类型

          Type elementType = Type.GetType(qualifiedName);
          

          【讨论】:

          • 我错过了什么吗,如果你有elementType,你不是已经有typeof(YourClass)了吗?
          【解决方案8】:

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

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

          【讨论】:

          • 您好,我误投了反对票,请编辑您的回复以便我撤消它。
          【解决方案9】:

          This 上面的解决方案对我来说似乎是最好的,但它对我不起作用,所以我做了如下:

          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 on AssemblyQualifiedNames

          【讨论】:

            【解决方案10】:

            您也可以获取没有程序集限定名称但也具有 dll 名称的类型,例如:

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

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

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

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

            【讨论】:

            • 这是“技巧”还是实际方法?我在文档中找不到这个 -_- 。顺便说一句,它结束了我 1 周的痛苦!谢谢
            • 这是一个更干净的解决方案,我很想看看是否有任何陷阱。
            • 这个答案中使用的形式也是一个完全限定的类型名称according to the MSDN grammar(所以它不是一个技巧)。形式为NamespaceTypeName, AssemblyNameSpec,其中AssemblyNameSpec 是没有任何属性的程序集的标识符。尽管这个答案与公认的答案基本相同,但我认为有些人更喜欢这个答案,因为它消除了程序集属性引入的一些“噪音”(例如Version、CulturePublicKeyToken)。幸运的是,这些属性是可选的。
            • 对于嵌套类型,你可能需要做类似AtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
            • 谢谢,这解决了我的问题。如果您尝试从另一个程序集获取 TypeName(假设您的解决方案有 2 个项目,并且您试图从另一个项目中获取位于一个项目中的类的类型,那么您需要提供完全限定的类名和程序集名称为逗号分隔,如@AsafPala 建议的那样。看到这里我有同样的问题和我添加的解决方案/解释stackoverflow.com/questions/54681389/…
            【解决方案11】:

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

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

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

            【讨论】:

            • 重新开启一个史诗般的老话题……恭喜。但是,我必须否决您的答案,因为 TO 实际上知道 Typename 并希望从中获取类型。顺便说一句:您通过 GetType(Namespace.ClassName) 引用哪种方法,如果它的 Type.GetType 仅适用于当前正在执行的程序集或 mscorlib 中的类型,但 TO sais none这些条件中的一个适用。
            • @HimBromBeere 感谢您的反对票。是像你这样的人让我失去了发表我的发现的动力。我仍在学习发展,我只是想帮助别人。现在你希望我回答你的问题?顺便说一句,我已经正确回答了这个问题。我创建实例的类位于不同的项目中,因此必须使用 AssemblyQualified 名称。因此,请在投票之前阅读其余的 cmets。 "该类型存在,在不同的类库中,我需要通过字符串名称获取它-Omu"
            【解决方案12】:

            如果程序集是 ASP.NET 应用程序构建的一部分,您可以使用 BuildManager 类:

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

            【讨论】:

            • 这是一个很棒的答案,应该在页面上更高。与获取程序集的限定类型名称的旧方法相比,它的工作原理非常简单。
            • @Graham 它已经过时,但它是必不可少的,永远不会过时或逻辑错误。每个类型都包含在一个特定的程序集中。在不知道容器的情况下,我们无法仅通过名称来识别类型。具有相同名称的多种类型是可能的。尽管在某些特定范围内,我们确实知道类型名称是唯一的。在许多情况下,甚至程序集本身也需要一个强名称(以确保唯一)。
            【解决方案13】:
            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;
            }
            

            【讨论】:

            • 这看起来不错,但是使用其他程序集类型的泛型呢?
            • @DemetrisLeptos(我知道评论很旧 - 但其他人可能仍然感兴趣):使用 int index = typeName.IndexOf('`'); if (index > 0) { typeName = _typeName.Substring(0, index + 2);请注意,泛型类型的T 已被剥离。
            【解决方案14】:

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

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

            当我只使用 namesspace.classname 来获取不同程序集中的类的类型时,我遇到了同样的情况,但它不起作用。仅当我在我的类型字符串中包含程序集信息时才有效,如上所示。

            【讨论】:

              【解决方案15】:

              如果它是一个嵌套类型,你可能会忘记转换一个 .到一个 +

              不管怎样,typeof( T).FullName 会告诉你应该说什么

              编辑:顺便说一句,使用(我相信你知道)只是编译时对编译器的指令,因此不会对 API 调用的成功产生任何影响。 (如果您有项目或程序集引用,这可能会产生影响 - 因此信息不是无用的,它只需要一些过滤......)

              【讨论】:

              【解决方案16】:

              如果程序集被引用并且类可见:

              typeof(namespace.a.b.ClassName)
              

              GetType返回null是因为找不到类型,使用typeof,编译器可能会帮你找出错误。

              【讨论】:

              • 类型存在,在不同的类库中,需要通过字符串名获取
              猜你喜欢
              • 1970-01-01
              • 2012-02-01
              • 2011-11-18
              • 2011-11-09
              • 1970-01-01
              • 2012-10-14
              • 1970-01-01
              相关资源
              最近更新 更多