2014-09-15 2 views
0

Краткое описание: Мне нужно продезинфицировать текст до его сохранения в базе данных. У нас есть проект, содержащий все модели, которые используются в нашем приложении MVC. Существует метод Save(T record), который сохраняет объект в базе данных. То, что мне было предложено сделать, - это очистить каждое свойство строки типа входящего объекта, прежде чем сохранять его в базе данных. Однако есть проблема: Как очистить свойства свойства настраиваемого типа данных от входящего объекта?Получить свойства свойства пользовательского типа данных с отражением C#

Длинное описание: Скажем, у меня есть класс, типа адреса и класс типа Человека, который имеет свойство типа Адрес:

public class Address 
    { 
     public string StreetName { get; set; } 
     public string City { get; set; } 
     public int StreetNumber { get; set; } 
    } 

    public class Person 
    { 
     public string PersonName { get; set; } 
     public Address HomeAddress { get; set; } 
    } 

Прежде чем я использовал этот общий метод для получения свойств тип строки:

 public static void SanitizeObject<TEntity>(TEntity record) 
     { 
      var props = 
       record.GetType().GetProperties() 
        .Where(x => x.CanRead && x.CanWrite) 
        .Where(x => x.PropertyType == typeof (string)); 
      foreach (var property in props) 
      { 
       string value = Convert.ToString(record.GetPropertyValue(property.Name)); 
       if (!string.IsNullOrEmpty(value)) 
       { 
        value = Sanitize(value); 
        record.SetPropertyValue(property.Name, value); 
       } 
      } 
     } 

в таком случае я санитарной обработки только Person.PersonName, однако, мне нужно дезинфицировать также Address.StreetName и Address.City

Есть ли способ написать это выражение лямбда, чтобы также получить свойства дочерней строки типа string? Как я должен выполнить это, чтобы получить все свойства строки типа, чтобы я мог их дезинфицировать?

+0

Вы пробовали что-нибудь? Я имею в виду, ваш объект санитации вы можете разбить на строки и объекты, а затем вызвать тот же метод на любых объектах, которые содержит ваш класс. – Hammerstein

+0

, даже если вы пишете лямбду, которая это делает. Вы должны спросить себя, может ли это быть прочитано кем-то? –

+0

Хаммерштейн, ты прав! Думаю, я должен это сделать! Спасибо! – John

ответ

2

Кажется, что вам нужен рекурсивный метод.

Псевдо-код:

public void SanitizeObject(object some) 
{ 
    // We get properties which are of reference types because we don't want to iterate value types (do you want to sanitize an integer...?) 
    foreach (PropertyInfo property in some.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(prop => !prop.PropertyType.IsValueType) 
    { 
     if (property.PropertyType == typeof (string)) 
     { 
     // Do stuff to sanitize the string 
     } 
     else 
     { 
      // Get properties declared in the concrete class (skip inherited members) 
      var properties = property.DeclaringType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); 

      // Does the property type has properties? 
      if (properties != null && properties.Length > 0) 
      { 
       // This gets the custom object and starts a recursion to sanitize its string properties if the object have string properties, of course... 
       SanitizeObject(property.GetValue(some)); 
      } 
     } 
    } 
} 

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

+0

Работает отлично! Спасибо! Но как насчет того, есть ли у меня свойство типа List

? – John

+1

@John Эй, ну, вам нужно будет сделать свойство property.GetValue', бросить его в 'IEnumerable ' и сделать foreach для каждого объекта и перезаписать для каждого из этих объектов –

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