繁体   English   中英

如何确定System.Type是自定义类型还是Framework类型?

[英]How do I determine if System.Type is a custom type or a Framework type?

我想清楚地确定我所拥有的类型是自定义类类型(MyClass)还是Framework(System.String)提供的类型。

反思是否有任何方法可以将我的类类型与system.string或其他Framework提供的类型区分开来?

安全检查类型是否为程序集的一部分的唯一方法是检查程序集的完全限定名称,该名称包含其名称,版本,区域性和公钥(如果已签名)。 所有.Net基类库(BCL)都由Microsoft使用其私钥签名。 这使得其他任何人几乎不可能创建具有与基类库相同的完全限定名称的程序集。

//add more .Net BCL names as necessary
var systemNames = new HashSet<string>
{
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
};

var isSystemType = systemNames.Contains(objToTest.GetType().Assembly.FullName); 

稍微不那么脆弱的解决方案是使用AssemblyName类并跳过版本号/文化检查。 这当然假设公钥在版本之间不会改变。

//add more .Net BCL names as necessary
var systemNames = new List<AssemblyName>
{
new AssemblyName ("mscorlib, Version=4.0.0.0, Culture=neutral, " +
                  "PublicKeyToken=b77a5c561934e089"),
new AssemblyName ("System.Core, Version=4.0.0.0, Culture=neutral, "+
                  "PublicKeyToken=b77a5c561934e089")
};

var obj = GetObjectToTest();

var objAN = new AssemblyName(obj.GetType().Assembly.FullName);

bool isSystemType = systemNames.Any(
        n =>  n.Name == objAN.Name 
           && n.GetPublicKeyToken().SequenceEqual(objAN.GetPublicKeyToken()));

大多数BCL都使用相同的密钥进行签名,但不是全部。 您可以使用AssemblyName类来检查公钥标记。 这取决于您的需求。

如果您只是想区分MyClassstring那么您可以直接检查这些类型:

Type typeToTest = GetTypeFromSomewhere();

if (typeToTest == typeof(MyClass))
    MyClassAction();
else if (typeToTest == typeof(string))
    StringAction();
else
    NotMyClassOrString();

如果您需要更一般地检查给定类型是否是框架类型,那么您可以检查它是否属于System命名空间:

// create an array of the various public key tokens used by system assemblies
byte[][] systemTokens =
    {
        typeof(System.Object)
            .Assembly.GetName().GetPublicKeyToken(),  // B7 7A 5C 56 19 34 E0 89
        typeof(System.Web.HttpRequest)
            .Assembly.GetName().GetPublicKeyToken(),  // B0 3F 5F 7F 11 D5 0A 3A 
        typeof(System.Workflow.Runtime.WorkflowStatus)
            .Assembly.GetName().GetPublicKeyToken()   // 31 BF 38 56 AD 36 4E 35 
    };

Type typeToTest = GetTypeFromSomewhere();

string ns = typeToTest.Namespace;
byte[] token = typeToTest.Assembly.GetName().GetPublicKeyToken();

bool isSystemType = ((ns == "System") || ns.StartsWith("System."))
                    && systemTokens.Any(t => t.SequenceEqual(token));

您可以检查声明类型的程序集。

object.GetType().Assembly

检查程序集是否属于CLR库:

myType.Module.ScopeName == "CommonLanguageRuntimeLibrary"

为解释在这里

并非所有框架类都在System命名空间中启动(它们也可以是Microsoft等)。

因此,您可以将已知框架类的位置与您正在测试的类型的位置进行比较,例如:

  if (String.CompareOrdinal(
        Path.GetDirectoryName(typeof(String).Assembly.Location), 
        Path.GetDirectoryName(typeof(MyType).Assembly.Location)
      ) == 0)
  {
    //Framework Type
  }
  else
  {
    //3rd Party DLL
  }

不是最好的解决方案; 但是比测试命名空间是否以System开头更安全(我可以创建一个以System不是框架类开头的命名空间)。

编辑

此外,除了上述测试之外,验证从全局程序集缓存加载类型也没有问题:

typeof(MyType).Assembly.GlobalAssemblyCache

暂无
暂无

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

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