Как я определяю если Система. Тип является пользовательским типом или типом Платформы?

Я хочу отчетливо определить, имеет ли тип, который я имею, пользовательский тип класса (MyClass) или один обеспеченный Платформой (Система. Строка).

Есть ли какой-либо путь в отражении, что я могу отличить свой тип класса от system.string или другой Основы, служившей типы?

11
задан Cœur 18 June 2017 в 04:09
поделиться

4 ответа

Единственный способ безопасно проверить, является ли тип частью сборки, - это проверить полное имя сборки, которое содержит ее имя, версию, язык и региональные параметры и открытый ключ (если он подписан). Все библиотеки базовых классов .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, чтобы просто проверить токен открытого ключа. Это зависит от ваших потребностей.

7
ответ дан 3 December 2019 в 07:10
поделиться

Если вы просто хотите различать MyClass и строку , то вы можете проверить эти типы напрямую:

Type typeToTest = GetTypeFromSomewhere();

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

Если вам нужна более общая проверка того, является ли данный type - это тип фреймворка, тогда вы можете проверить, принадлежит ли он пространству имен 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));
5
ответ дан 3 December 2019 в 07:10
поделиться

Не все классы фреймворка начинаются в пространстве имен 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
0
ответ дан 3 December 2019 в 07:10
поделиться

Вы можете проверить сборку, в которой объявлен тип.

object.GetType().Assembly
4
ответ дан 3 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: