使用反射清空ReadOnly-List

时间:2018-03-23 22:09:01

标签: c# reflection

我有一个自定义属性,用于标记要在返回之前删除的属性:

public HideAttribute:Attribute {}

public class UserData {
  public string Name {get;set;}
  [Hide]
  public string Phone {get;set;}
  [Hide]
  public List<Account> Accounts {get;} = new List<Account>();
}

现在,以下代码删除了数据:

protected void Remove<T>(T someData) {
  foreach(var property in typeof(T).GetProperties()) {
    if (property.GetCustomAttribute<HideAttribute>==null) continue;
    Type t=property.PropertyType;
    if (property.CanWrite) {
      property.SetValue(someData,null) 
    } else if (property.CanRead && t.IsGenericType && t.GetGenericTypeDefinition==typeof(List<>)) {
      property.Empty(someData); // Pseudocode; There is no such method
    }
  }
}

现在我想要的是:如果属性不可写,但是列表类型,我想清空该列表。

1 个答案:

答案 0 :(得分:2)

不要打扰仿制药;在这种情况下,使用泛型并不能获得任何东西,但它确实会让事情变得更难。 List<>实现了非通用IList interface,其中包含Clear()方法:

  

公共类列表&lt; T&gt; :IList&lt; T&gt;,ICollection&lt; T&gt;,IEnumerable&lt; T&gt;,       IEnumerable, IList ,ICollection,IReadOnlyList&lt; T&gt ;,IReadOnlyCollection&lt; T&gt;

在验证你实际上是在处理IList之后,你需要的只是你所需要的。为此,我们使用typeof(IList).IsAssignableFrom(t)检查您的属性类型是否可分配给IList

放在一起:

protected void Remove<T>(T someData) 
{
    foreach(var property in typeof(T).GetProperties()) 
    {
        if (property.GetCustomAttribute<HideAttribute>==null) 
            continue;
        Type t = property.PropertyType;
        if (property.CanWrite) 
        {
            property.SetValue(someData,null) 
        } 
        else if (property.CanRead && typeof(IList).IsAssignableFrom(t)) 
        {
            var collection = (IList)property.GetValue(data);
            collection.Clear();
        }
    }
}