我有一个管理对象如集合类List<Car>和List<Bike>它们属性附加伤害.
我想找到一种方法来在查找中获取每个集合的引用,这样我就可以实现诸如Add<Car>(myCar)或Add(myCar)(带反射)之类的方法,并将它添加到正确的集合中.
我试过以下,
public class ListManager
{
private Dictionary<Type, Func<IEnumerable<object>>> _lookup
= new Dictionary<Type, Func<IEnumerable<object>>>();
public ListManager()
{
this._lookup.Add(typeof(Car), () => { return this.Cars.Cast<object>().ToList(); });
this._lookup.Add(typeof(Bike), () => { return this.Bikes.Cast<object>().ToList(); });
}
public List<Car> Cars { get; set; }
public List<Bike> Bikes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是.ToList()创建一个新列表而不是引用,因此_lookup[typeof(Car)]().Add(myCar)只会添加到字典列表中.
这将有效:
public class ListManager
{
private Dictionary<Type, IList> _lookup
= new Dictionary<Type, IList>();
public ListManager()
{
_lookup.Add(typeof(Car), new List<Car>());
_lookup.Add(typeof(Bike), new List<Bike>());
}
public List<Car> Cars
{
get { return (List<Car>)_lookup[typeof(Car)]; }
}
public List<Bike> Bikes
{
get { return (List<Bike>)_lookup[typeof(Bike)]; }
}
public void Add<T>(T obj)
{
if(!_lookup.ContainsKey(typeof(T))) throw new ArgumentException("obj");
var list = _lookup[typeof(T)];
list.Add(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
这将是如果两个很好的Car和Bike同一类派生或实现相同的接口.然后,您可以向Add方法添加类型约束以获取编译错误,而不是ArgumentException.
编辑
上面的简单解决方案存在一个小问题.它只有在添加到列表中的对象类型完全是存储在_lookup字典中的类型时才有效.如果您尝试添加一个对象来源于Car或者Bike将抛出.
例如,如果您定义一个类
public class Batmobile : Car { }
Run Code Online (Sandbox Code Playgroud)
然后
var listManager = new ListManager();
listManager.Add(new Batmobile());
Run Code Online (Sandbox Code Playgroud)
会扔ArgumentException.
为了避免它,您将需要一个更复杂的类型查找方法.而不是简单_lookup[typeof(Car)]应该是:
private IList FindList(Type type)
{
// find all lists of type, any of its base types or implemented interfaces
var candidates = _lookup.Where(kvp => kvp.Key.IsAssignableFrom(type)).ToList();
if (candidates.Count == 1) return candidates[0].Value;
// return the list of the lowest type in the hierarchy
foreach (var candidate in candidates)
{
if (candidates.Count(kvp => candidate.Key.IsAssignableFrom(kvp.Key)) == 1)
return candidate.Value;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |