2015-02-11 77 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)),然后我们只是对它进行计数。

请注意,如果您有两个相同类型的属性 - 此模式将不起作用。