2015-10-01 5 views
1

Я использую веб-сервис, чтобы вернуть мне JsonAddressModel в обмен на uprn string в моем приложении в разных местах.Looping через свойства условно используя отражение

У меня есть требование распечатать адрес клиента в виде конкатенированного string на странице подтверждения моей формы.

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

Оригинальный метод

public static string ConcatAddress(JsonAddressModel jsonAddressModel) 
{ 
    StringBuilder builder = new StringBuilder(); 

    if (jsonAddressModel.saon.Replace(" ", "") != "" && jsonAddressModel != null) 
     builder.Append(jsonAddressModel.saon + ", "); 

    if (jsonAddressModel.paon != null) 
     builder.Append(jsonAddressModel.paon + ", "); 

    if (jsonAddressModel.thorofare != null) 
     builder.Append(jsonAddressModel.thorofare + ", "); 

    if (jsonAddressModel.dthorofare != null) 
     builder.Append(jsonAddressModel.dthorofare + ", "); 

    if (jsonAddressModel.posttown != null) 
     builder.Append(jsonAddressModel.posttown + ", "); 

    if (jsonAddressModel.county != null) 
     builder.Append(jsonAddressModel.county + ", "); 

    if (jsonAddressModel.postcode != null) 
     builder.Append(jsonAddressModel.postcode); 

    return builder.ToString(); 
} 

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

Новый метод

public static string ConcatAddress(JsonAddressModel jsonAddressModel) 
{ 
    StringBuilder builder = new StringBuilder(); 

    foreach (PropertyInfo prop in jsonAddressModel.GetType().GetProperties()) 
    { 
     if (prop != null) 
     {  
      builder.Append(prop.GetValue(jsonAddressModel, null) + ","); 
     } 
    }     
    return builder.ToString(); 
} 

Проблема

Хотя новый метод в настоящее время добавления каждого из правильных свойств, которые я хочу отображенных такие как Saon/Paon, Thorofare и т.д. Это также добавляя восточные, северные, uprn, а также такие вещи, как System.Runtime.Serialization.ExtensionDataObject, которые, очевидно, являются вещами, которые я не хочу включать в свою конкатенатную строку адреса.

Вопрос

Есть ли вообще оговаривая, какие именно свойства I позволяют дополнить здесь?

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

Я решил создать массив, но единственное поле, связанное с именем, которое я вижу, это SetMethod, который будет чем-то вроде SetMethod = {Void set_saon(System.String)}, но для каждого свойства, и я не совсем уверен, как получить ручку этого.

+0

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

+0

@ric Не могли бы вы привести пример этого, пожалуйста? – JsonStatham

+0

У вас есть контроль над 'JsonAddressModel'? – Ric

ответ

2

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

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

public static string ConcatAddress(JsonAddressModel jsonAddressModel) 
    { 
     var nonEmptyProperties = new [] { 
      jsonAddressModel.saon, 
      jsonAddressModel.paon, 
      jsonAddressModel.thorofare, 
      jsonAddressModel.dthorofare, 
      jsonAddressModel.posttown, 
      jsonAddressModel.county, 
      jsonAddressModel.postcode, 
     }.Where(s => !string.IsNullOrWhiteSpace(s)); 
     return string.Join(", ", nonEmptyProperties); 
    } 
+0

Свойства, которые я хочу, это те, что были в первом методе, около 4 дополнительных предметов, таких как те, которые я упоминал (восточные, северные, uprn & ExtensionDataObject), которые я не хочу. – JsonStatham

+0

Это лучше, чем отражение, хотя я бы пропустил переменную и просто «вернулся». – ErikE

+0

Как это знать, чтобы не поставить конечную запятую после почтового индекса? – JsonStatham

0

Да, и это довольно легко с Linq:

Вместо использования непосредственно

foreach (PropertyInfo prop in jsonAddressModel.GetType().GetProperties()) 
{ 
    // ... 
} 

вы можете использовать

var desiredProperties = new List<string> 
{ 
    "saon", 
    "paon" 
}; 
IEnumerable<PropertyInfo> pis = jsonAddressModel.GetType().GetProperties(); 
var filteredPropertyInfos = pis.Where(pi => desiredProperties.Contains(pi.Name)); 

foreach (PropertyInfo prop in filteredPropertyInfos) 
{ 
    // ... 
} 
2

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

public string ConcatProperties<T>(T input, params Func<T, string>[] propertyDelegates) 
{ 
    return string.Join(
     ",", 
     propertyDelegates 
      .Select(p => p(input)) 
      .Where(s => !string.IsNullOrEmpty(s)); 
} 

И использовать его как это:

var concatenatedString = ConcatProperties(thingy, 
    x => x.Foo, 
    x => x.Bar, 
    x => x.Wobble); 

Примечание: Это работает только со строковыми свойствами, для других необходимо преобразовать свойства строк (например, x => x.Wibble.ToString())

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