简体   繁体   English

从字符串.Net C#获取完全限定的类型名称

[英]Getting a fully qualified type name from a string .Net C#

我有一个字符串,如“Int”,“Double”,“DateTime”等。如何从此字符串中获取完全限定的名称?

It's worth bearing in mind that int isn't a type. 值得记住的是, int不是一种类型。 It's an alias provided by C# for the type System.Int32 . 它是C#为System.Int32类型提供的别名。 Bearing that in mind, and assuming you only care about core types, you can try: 考虑到这一点,假设您只关心核心类型,您可以尝试:

var typeName = "DateTime";

var systemTypesAssembly = Assembly.Load("mscorlib");

var type = (from t in systemTypesAssembly.GetTypes()
           where t.Name == typeName
           select t).FirstOrDefault();

Console.WriteLine(type.FullName);

As I said, this will not work for Int , but would work for Int32 which is the type it's aliased to. 正如我所说,这不适用于Int ,但适用于Int32 ,它是别名的类型。 This code also contains no error handling for where, for example, no type is found in mscorlib that matches the one you've entered in typeName 此代码也不包含错误处理,例如,在mscorlib中找不到与您在typeName输入的类型匹配的类型

Before I go any further, I'd like to point that there is no class in the .NET Framework base class library named Int . 在进一步讨论之前,我想指出.NET Framework基类库中没有名为Int类。 There is System.Int32 , that in C# happens to have an alias: int . System.Int32 ,在C#中恰好有一个别名: int

You can do this several ways. 你可以通过几种方式做到这一点

A simple but limited way to do this is to have a dictionary mapping strings to the corresponding FQNs: 一个简单但有限的方法是将字符串映射到相应的FQN:

public static IDictionary<string, string> FqnMap = new Dictionary<string, string>
{
    { "Int", "System.Int32" },
    { "Double", "System.Double" },
    { "DateTime", "System.DateTime" },
};

public string GetFqn(string name)
{
    return FqnMap[name]; // TODO: add error handling
}

A more complex but powerful way would involve using reflection to search all types from a set of assemblies. 更复杂但更强大的方法是使用反射从一组程序集中搜索所有类型。 Something like this: 像这样的东西:

public class FqnResolver
{
    public FqnResolver(IEnumerable<Assembly> assemblies)
    {
        Assemblies = new List<Assembly>(assemblies);
    }
    public FqnResolver(params Assembly[] assemblies) : this(assemblies as IEnumerable<Assembly>) { }
    public FqnResolver() : this(new Assembly[0]) { }

    public ICollection<Assembly> Assemblies { get; private set; }

    public string GetFqn(string name)
    {
        var candidates = from a in Assemblies
                         from t in a.GetTypes()
                         where t.Name == name
                         select t.FullName;
        return candidates.First(); // will throw if no valid type was found
                                   // and does not count duplicates
    }
}

This is not really doable in an efficient fashion in .Net. 这在.Net中并不是真正有效的方式。 In order to get a fully qualified name of a type you will need to have the Type object handy. 为了获得类型的完全限定名称,您需要使用Type对象。 And in order to get a Type object you typically need an instance, the fully qualified name, or you have to do a bit of searching. 并且为了获得Type对象,您通常需要一个实例,完全限定名称,或者您需要进行一些搜索。

The latter works but is not very efficient as you need to search through every assembly and type in the loaded AppDomain to find the correct answer. 后者工作但效率不高,因为您需要搜索每个程序集并键入已加载的AppDomain以找到正确的答案。

foreach ( var assembly in AppDommain.CurrentDomain.GetAssemblies() ) {
  foreach ( var type in assembly.GetTypes() ) {
    if ( type.Name == target ) {
      return type.FullName;
    }
  }
}

This solution still won't 100% work for you though. 尽管如此,这个解决方案仍然不会100%为您服务。 Primarily because there is no type "Int" in the .Net framework. 主要是因为.Net框架中没有类型“Int”。 It's actual type name is "Int32". 它的实际类型名称是“Int32”。

A type name like "String" can be ambiguous since it could refer to System.String or FooAssembly.String , so you have to search through all types in all loaded assemblies, which could yield multiple results. 像“String”这样的类型名称可能不明确,因为它可能引用System.StringFooAssembly.String ,因此您必须搜索所有已加载程序集中的所有类型,这可能会产生多个结果。 This bit of reflection could be slow, but you could do the obvious optimization of caching the results at the expense of memory: 这一点反射可能会很慢,但你可以以牺牲内存为代价来显着优化缓存结果:

static void Main(string[] args)
{
    string typeName = "String";
    foreach (var type in GetFullType(typeName))
    {
        Console.WriteLine(type.FullName);
    }
}

static IEnumerable<Type> GetFullType(string className)
{
    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        foreach (var type in assembly.GetTypes())
        {
            if (type.Name.Equals(className, StringComparison.OrdinalIgnoreCase))
            {
                yield return type;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM