【问题标题】:Getting a System.Type from type's partial name从类型的部分名称获取 System.Type
【发布时间】:2010-09-15 19:10:28
【问题描述】:

我想得到一个System.Type,只给string中的类型名称。

例如,如果我有一个对象:

MyClass abc = new MyClass();

然后我可以说:

System.Type type = abc.GetType();

但如果我只有:

string className = "MyClass";

【问题讨论】:

标签: c# .net reflection types


【解决方案1】:
Type type = Type.GetType("foo.bar.MyClass, foo.bar");

MSDN。确保名称为Assembly Qualified

【讨论】:

  • 重要说明:它需要完全限定的类型名称。
【解决方案2】:
Type type = Type.GetType("MyClass");

确保包含命名空间。控制区分大小写以及如果找不到类型名称是否引发异常的方法的重载。

【讨论】:

  • 来自文档,“如果类型在当前执行的程序集中或在 Mscorlib.dll 中,则提供由其命名空间限定的类型名称就足够了。”
  • 是当前执行程序集中的类型吗? OP没有指定。
【解决方案3】:

在获取类型后创建类的实例,并调用方法 -

Type type = Type.GetType("foo.bar.MyClass, foo.bar");
object instanceObject = System.Reflection.Activator.CreateInstance(type);
type.InvokeMember(method, BindingFlags.InvokeMethod, null, instanceObject, new object[0]);

【讨论】:

    【解决方案4】:

    如果无法使用typeof 运算符,Type.GetType(...) 有时可能会失败。

    相反,您可以反映当前域中的程序集以执行此操作。

    查看我对this thread的回复

    【讨论】:

      【解决方案5】:

      从当前或其他组件中获取类型的另一种方法。

      (假设类命名空间包含其程序集):


      public static Type GetType(string fullName)
      {
          if (string.IsNullOrEmpty(fullName))
              return null;
          Type type = Type.GetType(fullName);
          if (type == null)
          {
              string targetAssembly = fullName;
              while (type == null && targetAssembly.Length > 0)
              {
                  try
                  {
                      int dotInd = targetAssembly.LastIndexOf('.');
                      targetAssembly = dotInd >= 0 ? targetAssembly.Substring(0, dotInd) : "";
                      if (targetAssembly.Length > 0)
                          type = Type.GetType(fullName + ", " + targetAssembly);
                  }
                  catch { }
              }
          }
          return type;
      }
      

      【讨论】:

        【解决方案6】:

        下面是一个简单的方法,通过它的名称和参数创建和初始化一个新对象:

            //  Creates and initializes a new object from its name and parameters
            public Object CreateObjectByName(string name, params Object[] args)
            {
                string s = "<prefix>" + name;    // case sensitive; Type.FullName
                Type type = Type.GetType(s);
                Object o = System.Activator.CreateInstance(type, args);
                return o;
            }
        

        如何使用它的一个示例是读取包含类名[或部分类名]和参数的文件,然后将返回的对象添加到创建的对象所共有的基本类型的对象列表中。

        要查看您的班级名称 [或 ] 应该是什么样子,请暂时使用类似这样的名称 [如果您的班级名为 NewClass]:

            string z = (new NewClass(args)).GetType().FullName;
        

        【讨论】:

          【解决方案7】:

          这取决于类是哪个程序集。如果它在mscorlib 或调用程序集,你所需要的就是

          Type type = Type.GetType("namespace.class");
          

          但如果它是从其他程序集引用的,您需要这样做:

          Assembly assembly = typeof(SomeKnownTypeInAssembly).Assembly;
          Type type = assembly.GetType("namespace.class");
          
          //or
          
          Type type = Type.GetType("namespace.class, assembly");
          

          如果您只有类名“MyClass”,那么您必须以某种方式获取命名空间名称(或命名空间名称和程序集名称,以防它是引用程序集)并将其与类名连接起来。比如:

          //if class is in same assembly
          var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
          Type type = Type.GetType(namespace + "." + "MyClass");
          
          
          //or for cases of referenced classes
          var assembly = typeof(SomeKnownTypeInAssembly).Assembly;
          var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
          Type type = assembly.GetType(namespace + "." + "MyClass");
          //or
          Type type = Type.GetType(namespace + "." + "MyClass" + ", " + assembly.GetName().Name);
          

          如果您一无所有(甚至不知道程序集名称或命名空间名称),而只有类名,那么您可以查询整个程序集以选择匹配的字符串。 但这应该会慢很多

          Type type = AppDomain.CurrentDomain.GetAssemblies()
                                             .SelectMany(x => x.GetTypes())
                                             .FirstOrDefault(x => x.Name == "MyClass");
          

          请注意,这会返回第一个匹配的类,因此如果您在程序集/命名空间中有多个具有相同名称的类,则不需要非常准确。 在任何情况下,缓存值在这里都是有意义的。 稍微快一点的方法是假设有一个默认命名空间

          Type type = AppDomain.CurrentDomain.GetAssemblies()
                                             .Select(a => new { a, a.GetTypes().First().Namespace })
                                             .Select(x => x.a.GetType(x.Namespace + "." + "MyClass"))
                                             .FirstOrDefault(x => x != null);
          

          但这又是一个假设,即您的类型将与程序集中的其他随机类具有相同的命名空间;太脆,不太好。


          如果您想要其他域的类,您可以获取所有应用程序域的列表,遵循this link. 然后您可以对每个域执行如上所示的相同查询。如果尚未加载类型所在的程序集,则必须使用 Assembly.LoadAssembly.LoadFrom 等手动加载它。

          【讨论】:

          • 请注意,在所有加载的程序集中仅按名称搜索类型可能会在您的应用程序中打开一个安全漏洞 - 如果恶意行为者能够引入包含同名类的程序集和继承层次结构作为您正在搜索的层次结构。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 1970-01-01
          • 2011-02-04
          • 2010-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多