Как определить и проверить, является ли тип в сборке пользовательским или примитивным, используя отражение в .NET? - PullRequest
9 голосов
/ 04 сентября 2010

Можно ли во время выполнения проверить, является ли данный тип пользовательским типом данных или одним из примитивных типов данных .NET?

Я определил пользовательские типы в сборке, и все эти типы являются некоторыми структурами.Мне нужно вызывать методы определенных пользователем типов, чьи параметры являются этими структурами.Поэтому необходимо соответствующим образом заполнить данные перед вызовом этих функций во время выполнения с использованием отражения.

Теперь Есть ли в отражении какой-либо метод, с помощью которого мы можем отслеживать, что данный тип данных является пользовательским или примитивным типом данных.Я знаю об атрибуте IsClass, но мои целевые пользовательские типы данных не являются классами, эти открытые являются STRUCTS.

Ответы [ 7 ]

8 голосов
/ 05 сентября 2010

Я бы выбрал что-то вроде:

static bool IsFundamental(this Type type)
{
    return type.IsPrimitive || type.Equals(typeof(string)) || type.Equals(typeof(DateTime));
}

Выбор string и DateTime в качестве дополнения к типам, для которых IsPrimitive возвращает trueтем не менее, это субъективный вопрос, поскольку нет абсолютного списка ... окончательный выбор остается за вами (например, вы можете включить decimal);и это должно определенно быть задокументировано (по крайней мере, в комментарии, предпочтительно в XML).

4 голосов
/ 05 сентября 2010

На основании информации в этом вопросе вы можете сделать это, используя следующий код:

public static class TypeExtensions
{
    private static List<byte[]> tokens = new List<byte[]>() 
    {
        new byte[] {0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89},
        new byte[] {0x31, 0xbf, 0x38, 0x56, 0xad, 0x36, 0x4e, 0x35},
        new byte[] {0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a}
    };

    public static bool IsFrameworkType(this Type type)
    {
        if (type == null) { throw new ArgumentNullException("type"); }

        byte[] publicKeyToken = type.Assembly.GetName().GetPublicKeyToken();    

        return publicKeyToken != null && publicKeyToken.Length == 8
           && tokens.Contains(publicKeyToken, new ByteArrayEqualityComparer());
    }
}

Набор токенов открытого ключа действителен для .NET 2.0 и выше (включая.NET 4.0).Класс ByteArrayEqualityComparer выглядит следующим образом:

public class ByteArrayEqualityComparer : EqualityComparer<byte[]>
{
    public override bool Equals(byte[] x, byte[] y)
    {
        return x != null && y != null
                    && x.Length == 8 && y.Length == 8
                    && x[0] == y[0]
                    && x[1] == y[1]
                    && x[2] == y[2]
                    && x[3] == y[3]
                    && x[4] == y[4]
                    && x[5] == y[5]
                    && x[6] == y[6]
                    && x[7] == y[7];
    }

    public override int GetHashCode(byte[] obj)
    {
        return obj.GetHashCode();
    }
}

Затем вы будете использовать этот метод как:

Debug.WriteLine("Is type `string` a .NET Framework type? {0}",
   typeof(string).IsFrameworkType());
1 голос
/ 04 сентября 2010
0 голосов
/ 20 февраля 2014

Самый простой способ, которым я следовал, - это проверить пространство имен, чтобы выяснить, является ли оно одним из ваших пользовательских типов. Например, ваше пространство имен может быть «YourCompany.YourDepartment», и это можно проверить по пространству имен типа.

0 голосов
/ 27 февраля 2013

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

if(obj.GetType().Assembly.FullName.Contains("MyAssembly"))
{
    //User-defined type
}
else if(obj.GetType().FullName.StartsWith("System."))
{
    //.NET type
}
0 голосов
/ 05 сентября 2010

Похоже, вам нужно отличать типы, которые вы сделали сами, от всего остального.Просто создайте пользовательский атрибут, который вы добавляете в каждый из ваших типов, например:

[CustomAttribute]
struct MyDataType
{
....
}

Другой вариант - создать интерфейс, который реализуют все ваши собственные пользовательские типы.Тогда легко понять, нужно ли вам сделать что-то особенное с этим экземпляром, просто выполнив if (x is ICustom) ....

Если можно поместить их все в одно пространство имен или сборку, их также легко проверить с помощью отражения..

0 голосов
/ 04 сентября 2010

Очень простой, элементарный способ определить, предоставляется ли тип BCL / CLR:

var type = typeof(int);
var isSystemType = type.Assembly.FullName.StartsWith("mscorlib");

Имейте в виду, что использование Type.IsPrimitive вернет false для System.String, поэтому это зависит от того, какое определение «примитива» вы используете, в зависимости от того, подходит оно или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...