2015-02-11 67 views
0

我想從REST API反序列化xml輸出。解串後,我需要檢查響應是否有有效的數據。typeof(T)的內部列表

public class Response 
{ 
public UserWrapper Users { get; set; } 
public MovieWrapper Movies { get; set; } 
} 

public class UserWrapper 
{ 
    [XmlElement("User")] 
    public User[] UserList { get; set; } 
} 

public class MovieWrapper 
{ 
    [XmlElement("Movie")] 
    public Movie[] MovieList { get; set; } 
} 

public static bool isValidUserResponse(this Response response) 
{ 
return response.Users != null && response.Users.UserList != null 
} 

public static bool isValidMovieResponse(this Response response) 
{ 
return response.Movies!= null && response.Movies.MovieList != null 
} 

XML響應結構

<Response> 
<Users> 
    <User>...</User> 
    <User>...</User> 
    <User>...</User> 
</Users> 
</Response> 

<Response> 
<Movies> 
    <Movie>...</Movie> 
    <Movie>...</Movie> 
    <Movie>...</Movie> 
</Movies> 
</Response> 

如何讓我的isValidUserResponse()和isValidMovieResponse()作爲一個通用的方法是什麼?

+7

你不清楚你在問什麼 - 我們不知道'MovieList'會被放到什麼地方,或者'Response'是什麼等等。請提供更多的上下文 - 以及如何做這個的例子*沒有*泛型將是一個好的開始......(我也建議你開始遵循.NET命名約定,並將你的方法體改爲'return response.Users!= null && response.Users.UserList!= null; '。) – 2015-02-11 07:38:34

+0

我會開始將你的列表命名爲'List'而不是'UserList','MovieList'等。這將使得使用接口的匹配成爲可能。 – 2015-02-11 07:41:37

+0

@JonSkeet我已經更新了我的問題。希望這可以幫助。也感謝堅持我的.NET公約。 – 2015-02-11 07:55:53

回答

3

你不能只用泛型 - 至少,不容易。您可以類似:

public static void IsValidResponse<T>(this Response response, 
    Func<Response, T> firstPropertyFetcher, 
    Func<T, object> secondPropertyFetcher) where T : class 
{ 
    T property = firstPropertyFetcher(response); 
    return property != null && secondPropertyFetcher(property) != null; 
} 

,並稱之爲:

response.IsValidResponse(r => r.Users, u => u.UserList); 
response.IsValidResponse(r => r.Movies, u => u.MovieList); 

...但我不知道這是任何清潔劑。

或者你可能使用反射來檢查Response中的所有屬性,並找到具有「目標」類型的屬性,並驗證這些屬性......但它有點難看。

您是否需要分別驗證響應的每個部分?如果沒有,你可以考慮給每個班級自己的IsValid方法。

另外,我相信有一些通用的開源驗證項目可以幫助你 - 但我沒有任何經驗。

2
public class Response 
{ 
    public UserWrapper Users { get; set; } 
    public MovieWrapper Movies { get; set; } 

    public Response() 
    { 
     Users = new UserWrapper(); 
     Movies = new MovieWrapper(); 
    } 

    public bool IsValid<T>() where T : IList 
    { 
     var property = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).First(p => p.PropertyType.Equals(typeof(T))); 
     var collection = property.GetValue(this) as IList; 
     return collection.Count > 0; 
    } 
} 

public class User 
{ 
    // ... 
} 

public class Movie 
{ 
    // ... 
} 

public class UserWrapper : List<User> 
{ 
    // ... 
} 

public class MovieWrapper : List<Movie> 
{ 
    // ... 
} 

然後我們得到:

static void Main(string[] args) 
     { 
      var res = new Response(); 
      res.Users.Add(new User()); 
      Console.WriteLine(res.IsValid<UserWrapper>().ToString()); // "true" 
      Console.WriteLine(res.IsValid<MovieWrapper>().ToString()); // "false" 
     } 

所以這裏發生的事情:this.GetType()給我們Response類型的對象,它存儲所有關於它的元數據;我們獲取屬於該實例的所有公共屬性,並查找返回類型(PropertyType)的第一個屬性,該屬性與我們正在尋找的屬性相同:T類型。 我們使用property從實例中獲取相關集合(property.GetValue(this)),然後我們只是對它進行計數。

請注意,如果您有兩個相同類型的屬性 - 此模式將不起作用。