[英]How do I get a List<T> property in a class via reflection in C#?
我有一个叫做Animals
的类,其中包含两个List<T>
。 一个是熊的清单,一个是企鹅的清单。
我可以通过只在animals
变量上调用Bears
来轻松获得Bears
列表-但是如何通过反射得到它呢?
我创建了一个静态帮助器类ListHelper
,该类具有将Bear
或Pinguin
作为通用类型的通用方法,并且将动物作为参数,如果Bear
是通用类型, 则应返回ListHelper
列表。
那不会发生。 相反,它崩溃并显示以下消息: System.Reflection.TargetException: 'Object does not match target type
,我不明白为什么,因为通过调试器检查类型时,类型是正确的。
下面是完全“有效”的示例。
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System;
class ReflectionTrouble
{
static void Main(string[] args)
{
var animals = new Animals
{
Bears = new List<Bear> {new Bear {Name = "Bear1"}, new Bear {Name = "Bear 2"}},
Pinguins = new List<Pinguin> {new Pinguin {Name = "Pingo1"}, new Pinguin {Name = "Pingo2"}}
};
var lists = ListHelper.GetList<Bear>(animals);
foreach (var bear in lists)
{
Console.WriteLine(bear.Name);
}
//expected to have printed the names of the bears here...
}
}
public static class ListHelper
{
public static IEnumerable<T> GetList<T>(Animals animals)
{
var lists = animals.GetType().GetRuntimeProperties().Where(p => p.PropertyType.IsGenericType);
foreach (var propertyInfo in lists)
{
var t = propertyInfo.PropertyType;
var typeParameters = t.GetGenericArguments();
foreach (var typeParameter in typeParameters)
{
if (typeParameter == typeof(T))
{
// This is where it crashes.
var list = (IEnumerable<T>) propertyInfo.GetValue(t);
return list;
}
}
}
return Enumerable.Empty<T>();
}
}
public class Animals
{
public IList<Bear> Bears { get; set; }
public IList<Pinguin> Pinguins { get; set; }
}
public class Bear
{
public string Name { get; set; }
}
public class Pinguin
{
public string Name { get; set; }
}
您误会了如何调用propertyInfo.GetValue
。 传递给它的参数应该是要获取其属性值的对象。 因此,在这种情况下,您需要动物的属性值,因此该行应为:
var list = (IEnumerable<T>) propertyInfo.GetValue(animals);
进行此更改后,您的代码将使我不堪重负。
我认为在这里,词典比反射更好。 开箱即用的字典应该能够处理所有情况,并提供更好的性能。 如果要将其封装在类中,则它可能看起来像这样。
public interface IAnimal
{
string Name { get; set; }
}
public class Animals
{
private readonly ConcurrentDictionary<Type, IList<IAnimal>> AnimalDictionary;
public Animals(IList<IAnimal> animals)
{
this.AnimalDictionary = new ConcurrentDictionary<Type, IList<IAnimal>>();
this.Add(animals);
}
public Animals(IAnimal animal)
{
this.AnimalDictionary = new ConcurrentDictionary<Type, IList<IAnimal>>();
this.Add(animal);
}
public IList<IAnimal> Get<T>() where T : IAnimal
{
if (this.AnimalDictionary.ContainsKey(typeof(T)))
{
return this.AnimalDictionary[typeof(T)];
}
return (IList <IAnimal>)new List<T>();
}
public void Add(IList<IAnimal> animals)
{
foreach (IAnimal animal in animals)
{
this.Add(animal);
}
}
public void Add(IAnimal animal)
{
this.AnimalDictionary.AddOrUpdate(animal.GetType(),
new List<IAnimal>{animal},
(type, list) =>
{
list.Add(animal);
return list;
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.