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

Nil*_*Das 11 c# reflection types

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

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

Bea*_*key 7

安全检查类型是否为程序集的一部分的唯一方法是检查程序集的完全限定名称,该名称包含其名称,版本,区域性和公钥(如果已签名).所有.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); 
Run Code Online (Sandbox Code Playgroud)

稍微不那么脆弱的解决方案是使用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()));
Run Code Online (Sandbox Code Playgroud)

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


Luk*_*keH 5

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

Type typeToTest = GetTypeFromSomewhere();

if (typeToTest == typeof(MyClass))
    MyClassAction();
else if (typeToTest == typeof(string))
    StringAction();
else
    NotMyClassOrString();
Run Code Online (Sandbox Code Playgroud)

如果您需要更一般地检查给定类型是否是框架类型,那么您可以检查它是否属于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));
Run Code Online (Sandbox Code Playgroud)