簡體   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