【问题标题】:C# look up type by source name and get source name for typeC# 按源名称查找类型并获取类型的源名称
【发布时间】:2015-04-21 13:37:18
【问题描述】:

我需要按名称获取 C# 类型,其中接口应该与 typeof 几乎相同,除了字符串是在运行时命名的,而不是在编译时命名的类型 - 即 typeof(x) == runtime_typeof("x") 对于所有 @ 987654323@。相当关键的是,我还需要处理各种泛型情况,例如泛型定义和泛型类型。

我在 C# 中看到了其他一些按名称获取类型的解决方案,但它们似乎都涉及 CLR 错位名称而不是 C# 源名称。

此外,我需要检索给定 Type 对象的源名称,该对象应具有相同的形式。

如何通过 C# 源名称查找类型并从类型中检索 C# 源名称?

编辑:程序集限定名称和 C# 源名称​​不是一回事。因此问题的明确性。

我真正在寻找的是名称应该与您从 C# 源代码中引用它们时使用的名称相同 - 所以 IEnumerable<T>IEnumerable<>,而不是 IEnumerable[1]` 或任何。要求完整的命名空间对我来说很好,而且我已经知道要查看哪些程序集,所以这主要是涉及泛型和名称修改时会发生什么的问题。

【问题讨论】:

  • Assembly.GetTypeType.GetType ?顺便说一句,它看起来像 XY 问题。你想达到什么目的,也许有更好的解决方案?
  • 我不确定我是否理解您的要求。对此感到抱歉。但对于泛型类型,您需要使用反引号、泛型参数计数和 [类型名称]。例如Type t = Type.GetType("System.Collections.Generic.List1[System.Int32]"); Type t2 = Type.GetType("System.Collections.Generic.Dictionary2[System.Int32,System.String]");
  • 如果你举个例子,也许这个问题会更清楚? 源名称到底是什么?如果副本没有回答您的问题,我不清楚您的问题是什么。
  • @Liam:如果您只是从 C# 源代码中引用它,您将使用的名称。
  • 按命名空间完全限定名称对我来说很好。但是限定名和程序集限定名是有区别的,尤其是在泛型方面。

标签: c# .net


【解决方案1】:
  • 通过字符串源代码表示检索类型名称

经过深思熟虑,我想我终于找到了解决您核心问题的方法。如果您真正需要的是一个可以接受字符串参数的 typeof() 函数,那么您可以使用 CSharpCompilerServices 来实现:

 // set the assembly location, namespace, and string name of desired type
 var assemblyLocation = Assembly.GetExecutingAssembly().Location;
 var namespaceToType = "Namespace.Of.Type";
 var desiredType = "C<int>";

 // write some code using above parameters
 var template = "using {0};\nusing System;\npublic class Snippet {{\n\tpublic static Type main() {{\n\t\treturn typeof({1});\n\t}}\n}}";

 var code = string.Format(template, namespaceToType, desiredType);

 // compile code in memory, then return value via reflection
 var provider = CodeDomProvider.CreateProvider("CSharp");
 var parameters = new CompilerParameters();
 parameters.GenerateExecutable = false;
 parameters.GenerateInMemory = true;
 parameters.ReferencedAssemblies.Add(assemblyLocation);
 var results = provider.CompileAssemblyFromSource(parameters, code);
 return mytype = results.CompiledAssembly.GetType("Snippet").GetMethod("main").Invoke(null, null) as Type;

我无法谈论此解决方案的性能,但从 cmets 看来,您正在构建过程中使用它,所以(希望)这不会太重要。

我将旧答案留给后人,因为我收到了一些赞成票:

根据MSDN 此处的文章:

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

  • 通过命名空间限定名称检索类型(部分匹配)

    Assembly.GetExecutingAssembly()
            .DefinedTypes.Where(type => type.Name.Contains("MyType")).First();
    

【讨论】:

  • 一个警告:Type.GetType 需要“程序集限定名称”才能正常工作。
  • 在您输入评论时正在编辑 :)。
  • 程序集限定名称和 C# 源名称不是一回事。
  • 我知道,但是只要在当前执行的程序集中定义了类型,命名空间限定名称就足够了。如果上述方法不够用,我贴了一个替代方法。
猜你喜欢
  • 2013-11-29
  • 1970-01-01
  • 2012-07-02
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
相关资源
最近更新 更多