Фильтрация свойств объектов по имени - PullRequest
1 голос
/ 05 декабря 2008

Я делаю несколько простых проверок работоспособности для различных типов. Текущий тест, над которым я работаю, проверяет, заполнены ли их свойства. В этом случае заполненный определяется как ненулевой, имеющий длину больше нуля (если строка) или не равную 0 (если целое число).

«Хитрая» часть этого теста состоит в том, что некоторые свойства невосприимчивы к этой проверке. Сейчас я использую гигантский оператор if, который отсеивает свойства, которые не нужно проверять.

//Gets all the properties of the currect feature.
System.Reflection.PropertyInfo[] pi = t.GetProperties();

for(int i = 0; i < pi.Length; i++)
{
    if(!pi[i].Name.Equals("PropertyOne") 
    && !pi[i].Name.Equals("PropertyTwo") 
    && !pi[i].Name.Equals("PropertyThree") 
            //... repeat a bunch more times
    && !pi[i].Name.IndexOf("ValueOne") != -1 
    && !pi[i].Name.IndexOf("ValueTwo") != -1 
            //... repeat a bunch more times
    {
        //Perform the validation check.
    }                 
}

При профилировании я заметил, что оператор if на самом деле работает хуже, чем отражение (не то, что отражение быстро светится). Есть ли более эффективный способ фильтрации свойств нескольких разных типов?

Я думал о массивном регулярном выражении, но я не уверен, как его отформатировать, плюс оно, вероятно, было бы нечитаемым, учитывая его размер. Я также рассмотрел вопрос о сохранении значений в List и последующем использовании Linq, но я не уверен, как обрабатывать случаи, в которых используется String.IndexOf (), чтобы определить, содержит ли свойство определенное значение.

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 05 декабря 2008

Создайте HashSet «точные имена» с PropertyOne, PropertyTwo и т. Д., А затем список «частичные имена» с ValueOne, ValueTwo и т. Д. Затем:

var matchingProperties = pi.Where(exactNames.Contains(pi.Name) ||
                          partialNames.Any(name => pi.Name.Contains(name));

foreach (PropertyInfo property in matchingProperties)
{
    // Stuff
}

(Странный отступ только для того, чтобы избежать переноса.)

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

0 голосов
/ 05 декабря 2008

Возможно, вы захотите украсить свои свойства атрибутами, которые сообщают, какое действие необходимо с ними сделать.

public class MyClass {

   [CheckMe]
   public int PropertyOne { get; set; }

   [DontCheckMe]
   public int PropertyTwo { get; set; }

}
0 голосов
/ 05 декабря 2008

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

List<System.Reflection.PropertyInfo> pi = type.GetProperties().ToList();

var matchingProperties = pi.Where( prop => !PropertyExclusionSet.Contains( prop.Name )
&& !PropertiesPartialSet.Any( name => prop.Name.Contains( name ) ) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...