我正在编写一个程序并发现了一些常见的行为,所以我认为这对于抽象基类来说是一个合适的用例.
这是我的抽象基类的简化版本:
public abstract class BehaviorClass<T> where T: IDomainObj { protected BehaviorClass(var x){...} public abstract void Create(List<T> list,out string message); public abstract void Delete(List<T> list,out string message); ... }
这是我的派生类的简化版本:
public class DbSheets : BehaviorClass<Sheet> { public override void Create(List<Sheet> sheets,out string message){...} public override void Delete(List<Sheet> sheets,out string message){...} ... }
这是我想对派生类进行操作的通用方法:
public void Import<DbObj>() where DbObj : BehaviorClass<IDomainObj> { var instance = (DbObj)Activator.CreateInstance(typeof(DbObj),DbAccessor); // STEP 1: Remove existing values var existingValues = instance.Read(); instance.Delete(existingValues,out message); // STEP 2: Create new IDomainObjects var domainObjects = //LINQ Query.ToList(); // STEP 3: Add new IDomainObjects to the instance instance.Create(domainObjects,message); }
internal class Program { ... intermediary.Import<DbSheets>(); ... }
The type ‘namespace.DbSheets’ cannot be used as type parameter ‘DbObj’ in the generic type or method
'intermediary.Import<DbObj>()'
.
There is no implicit reference conversion from ‘namespace.DbSheets’ to'namespace.BehaviorClass<IDomainObj>'
.
我的思考过程总结:
本质上,我想要一个泛型方法只对从BehaviorClass派生的类进行操作,因为我可以可靠地知道它们共享一组常用的方法和属性. Resharper说如果我删除Import方法的泛型约束,代码将编译.我宁愿不删除该约束,因为此方法特别依赖于此共享行为将存在的事实.
解决方法
在我看来,你需要两个泛型类型参数:
public void Import<TBehavior,TDomain>() where TBehavior : BehaviorClass<TDomain> where TDomain : IDomainObj { var instance = (TBehavior) Activator.CreateInstance(typeof(TBehavior),DbAccessor); // STEP 1: Remove existing values var existingValues = instance.Read(); instance.Delete(existingValues,out message); // STEP 2: Create new IDomainObjects var domainObjects = //LINQ Query.ToList(); // STEP 3: Add new IDomainObjects to the instance instance.Create(domainObjects,message); }
现在你应该可以打电话:
Import<DbSheets,Sheet>();
之前的问题是DbSheets不是BehaviorClass< IDomainObj> – 你不能调用sheet.Create(例如新的List< IDomainObj>()).
稍微笨拙的是必须指定两个类型参数,并且可能有办法避免它,但我认为这是最简单的方法.