2015-10-01 58 views
1

我正在使用Web服務向我返回一個JsonAddressModel,作爲我在各個地方的應用程序中的上行string的回報。有條件地使用反射循環訪問屬性

我有要求在我的表單的確認頁上打印客戶地址作爲級聯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(); 
} 

問題

而新的方法現在每個附加我想顯示如薩翁/ PAON,Thorofare的等,這是正確的屬性還附加eastings,northings,uprn以及像System.Runtime.Serialization.ExtensionDataObject這些顯然是我不希望包含在我的拼接地址字符串中的東西。

問題

反正是有確切規定哪些屬性允許我在這裏的附加?

我不認爲BindingFlags將在我的實例中工作,因爲如前所述,我從Web服務接收此模型,並且我想要的和不想要的屬性都分別爲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

我想要的屬性是第一種方法中的屬性,這些屬性包括我提到的屬性(eastings,northings,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()