определить сложный тип из примитивного типа, используя отражение - PullRequest
9 голосов
/ 12 мая 2010

Я пишу инструмент, в котором мне нужно подумать о методах, и если параметры методов имеют сложный тип, то мне нужно выполнить определенный тип действий, таких как их создание и т. Д.

Теперь я увидел свойство IsPrimitive в переменной Type. Тем не менее, он показывает string и decimal как сложные типы, что технически не является неправильным. Однако я действительно хочу отличать типы классов, созданные разработчиками, от типов данных, определенных системой.

Есть ли способ, которым я могу это сделать?

Ответы [ 4 ]

8 голосов
/ 12 мая 2010

decimal определенно - «сложный тип»; C # может иметь ключевое слово для него, но это не примитив CLI. Строка, с которой вы могли бы поспорить в любом случае - это на самом деле тип сам по себе (неопределенный размер и т. Д. - единственные вещи, которые можно сравнить дистанционно, - это массивы).

Тем не менее, просто нет способа определить, чего вы хотите здесь. лучший , который вы можете сделать, - это проверить известные системные сборки (или, возможно, ключи подписи). В конце концов, I может написать сборку с именем System.something.dll или Microsoft.something.dll, с типами в пространстве имен System.Foo.Bar (это также зависит от того, каким параноиком вы хотите быть, Конечно).

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

4 голосов
/ 15 марта 2013

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

if (property.PropertyType.Namespace.StartsWith("MyApp.MyNamespace"))
{ 
      // logic for properties in MyNamespace
}

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 12 мая 2010

Я не уверен, что есть более элегантный метод, но я полагаю, что если вы проверите пространство имен типа или AssemblyQualifiedName по пространству имен System и / или системным сборкам, то все будет работать нормально.

0 голосов
/ 12 мая 2010

Не совсем уверен, чем использование встроенных типов отличается от созданных пользователем типов. Ваша большая проблема - создание экземпляров типов, которые не имеют конструкторов без параметров.

Что бы вы ни делали, вам придется преобразовывать их в массивы объектов, чтобы вы могли передать их MethodInfo.Invoke, поэтому в какой-то момент вам нужно будет сделать Activator.CreateInstance .

Если вы предоставляете пользовательский интерфейс, в котором пользователь может вводить данные в поля, а затем нажимать кнопку для вызова метода, вам лучше всего использовать Reflection для поиска статических методов TryParse / Parse для типа и вызова их в Для проверки / анализа ввода.

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

var parseMethod = typeof(int).GetMethods().FirstOrDefault(
    m => m.IsStatic && 
        m.Name == "TryParse" && 
        m.GetParameters().Length == 2 && 
        m.GetParameters()[0].ParameterType == typeof(string) && 
        m.GetParameters()[1].IsOut);
if(parseMethod != null) {
    bool result = (bool)parseMethod.Invoke(null, new object[]{"45", null});
    //result == true
    result = (bool)parseMethod.Invoke(null, new object[] { "blah", null });
    //result = false
}
...