我有两种基类:
public class Parent { }
public abstract class Child : Parent
{
string ChildKey { get; set; }
}
来自家长,有很多孩子:
public class Kid1 : Parent { public string Name { get; set; } }
public class Kid2 : Parent { public long Number { get; set; } }
...
以及许多儿童作为特殊群体的具有额外属性的孩子:
public class Child1 : Child { public string Street { get; set; } }
public class Child2 : Child { public long Account { get; set; }}
现在我有两个通用的存储库类,其中“Special One”通过使用额外的过滤器对更多属性更具体:
public class Repository<T> : IRepository<T> where T : Parent
{
public IEnumerable<T> GetAll() { return something; }
}
public class ChildRepository<T> : Repository<T>, IChildrenRepository<T> where T : Child
{
public override IEnumerable<T> GetAll() { return base.GetAll().Where(x => x.ChildKey == "y"); }
}
使用接口:
public interface IRepository<T> where T : Parent
{ IEnumerable<T> GetAll(); }
public interface IChildRepository<T> : IRepository<T> where T : Child { }
我还需要GetAll()的类型安全性 - 结果。
现在我需要一个通用方法来创建所需的存储库:
IRepository<T> GetRepository() where T : WhatConstraint
{
if (typeof(Child).IsAssignableFrom(T))
return new ChildRepository<T>(); // return 1
return new Repository<T>(); // return 2
}
正确的约束是什么? return 1需要Child-Constraint(返回2是错误的),说类型T不能用作方法中的类型参数,因为没有从T到Child的隐式引用转换。
T:Child-constraint在ChildRepository中更精确(因此我很有用,因为我可以依赖一些属性)。如果我使用相同的T:存储库的父约束,我必须输入 - 检查T是否始终从Child派生...
这有什么解决方案吗?
答案 0 :(得分:0)
好的,这是一个详细的解决方案(可以写得更短,也更不易读)。由于Repository和ChildRepository存在冲突的约束(这对存储库有好处,但对GetRepository-factory不利),我无法使用new-keyword创建ChildRepository。我必须通过CreateInstance创建这个对象。
IRepository<T> GetRepository() where T : Parent
{
if (typeof(Child).IsAssignableFrom(T))
{
Type childType = typeof(T); // which is both, Parent and Child
Type classType = typeof(ChildRepository<>);
Type[] typeParams = { childType };
Type repositoryType = classType.MakeGenericType(typeParams);
return Activator.CreateInstance(resultType) as IRepository<T>;
}
return new Repository<T>();
}
此解决方案的缺点:更复杂的代码分析,不清楚结果的可空性,不是非常直观的可读性(尤其是现有的约束)。但它确实有效。