2013-04-30 2 views
1

Предположим, у меня есть класс (что-то вроде этого):Получить пользовательские типы недвижимости с помощью отражения

public class User 
{ 
    public Guid Id { get; set;} 
    public DateTime CreationDate { get; set; } 
    public string Name { get; set; } 
    public UserGroup Group { get; set; } 
} 

Есть ли способ получить все виды собственности, которые не являются частью .NET Framework. Итак, в этом случае я хочу получить только UserGroup? Это возможно ?

Самое лучшее, что я могу придумать что-то вроде:

IEnumerable<Type> types = typeof(User).GetProperties().Where(p => !p.PropertyType.Namespace.StartsWith("System.")).Select(t => t.PropertyType);

Но это выглядит как хак-работу. Извините, если он не смог найти ничего подобного и извините за форматирование, сделал все возможное.

ответ

1

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

public class User 
{ 
    public Guid Id { get; set; } 
    public DateTime CreationDate { get; set; } 
    public string Name { get; set; } 
    [CustomProperty] 
    public UserGroup Group { get; set; } 
} 

Вы могли бы использовать отражение для запроса всех свойств, которые имеют этот атрибут , Это даст вам возможность включить/исключить любые объекты.


К сожалению, я забыл упомянуть, что я не могу изменить объекты домена. (не может добавить атрибут).

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

class UserMetadata 
{ 
    ... 
    [CustomProperty] 
    public UserGroup Group { get; set; } 
} 

[MetadataType(typeof(UserMetadata)] 
public class DomainUser : User 
{ 
} 
+0

Извините, что забыл упомянуть, что я не могу изменить объекты домена. (не может добавить атрибут). Я ценю вашу помощь :) –

+1

@DimitarDimitrov не беспокоится, см. Обновление. – James

+1

Спасибо, это подход, о котором я не думал. Я сделаю снимок (выглядит чище). –

1

Отражение всегда своего рода хакерство, так что да, это похоже на hackjob.

Но анализ объекта, класс, должен быть выполнен с отражением. Таким образом, вы делаете это правильно.

Одна ловушка. Вы сами можете создавать свои собственные типы в пространстве имен «Система». Это испортило бы ваш поиск. Вы также можете проанализировать сборку типа свойства, но тогда вам нужно знать все сборки .NET, которые являются большим списком.

+1

Хотя ваш технически правильный, вы никогда не должны действительно добавляйте свои собственные пользовательские типы в пространство имен 'System' - это нарушает [правила пространства имен] (http://msdn.microsoft.com/en-GB/library/893ke618 (v = vs.71) .aspx). – James

0

Все, что вы сделали хорошо, вы могли бы сделать что-то подобное и использовать метод Except.

public static Type[] GetNonSystemTypes<T>() 
{ 
    var systemTypes = typeof(T).GetProperties().Select(t => t.PropertyType).Where(t => t.Namespace == "System"); 
    return typeof(T).GetProperties().Select(t => t.PropertyType).Except(systemTypes).ToArray(); 
} 
+0

Не совсем понятно, почему введение здесь «Исключить» помогает? Все, что он делает, это сделать код длиннее. – James

+0

@James только потому, что код длиннее, не означает, что он хуже - большинство времени infact, это лучше. Просто представить альтернативный способ сделать это? – LukeHennerley

+0

Более длинный код лучше, если он действительно помогает в некотором роде - это не так. Это похоже на высказывание вместо написания 'var i = 0', вы можете сделать' int i; i = 0; '. Зачем делать что-то в 2 строках, если это можно сделать в одном, особенно если оно не добавляет * ничего в код? – James

0

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

bool wasLoadedFromAssemblyCache = typeof(T).Assembly.GlobalAssemblyCache; 
+0

Хороший способ мышления, но, что, если Димитар также помещает свои DLL в GAC? –

+0

@MartinMulder: конечно. Я имел в виду этот пример больше как идею для проверки свойств Ассамблеи в целом, не обязательно свойство GAC. Например, вы можете проверить имя сборки, если пользовательские типы находятся в одной сборке. – gabnaim

Смежные вопросы