背景:我们使用基于ASP.NET Core开发的基于ASP.NET Core的Web应用程序在DI&通用存储库模式。因此,大多数事情都是使用接口完成的。现在,我们已经达到了主表维护模块。我们不希望为所有10-20个主表复制相同的服务(由存储库支持)类。
因此,我们创建了一个_ModelMasterBase
类,并从中派生了所有主表类。所有主表的CRUD都是相同的。接下来,我们实现了MasterRepository<T>
,MasterService<T>
及其接口等内容。现在一切都必须使用<T>
,其中T
是在页面上选择的主表的类型,以执行CRUD。
最初,我预计IMasterService<_ModelMasterBase>
的实例可以转换为 IMasterService<T>
- 再次T
可以是来自_ModelMasterBase
的任何子类派生 - 但似乎不可能!我尝试过操作符,强制转换,几乎我可以google的一切!同样由于存储库模式,所有内容都必须是强类型的。
现在,我们已经根据SO Post使用该技巧将子obj转换为基类obj -
DerivedClass B = new DerivedClass();
BaseClass bc = JsonConvert.DeserializeObject<BaseClass>(JsonConvert.SerializeObject(B));
我知道它有点肮脏的伎俩,但有时它很方便维持设计和复杂性之间的权衡。我们谨慎使用它。如果我想将MyService<Base>
投射到MyService<Child>
或者你可以忘记这一切,并指导我为我的所有主表提供单点CRUD服务 - 复制相同的东西10-20次似乎是不合理的。对不起,我无法深入解释,因为它会延长帖子。
这是一个v.basic sample of my code structure ,最后你会看到我们想要实现的目标。希望它有所帮助。
解决方案:
根据mkArtak的建议,我能够通过使用来破解它 'Covariance'概念(example)。这是我的 updated code sample. 现在所有主表都有一个控制器和服务层!
答案 0 :(得分:1)
这种事情闻起来像你应该更喜欢构成而不是继承。由于您已经说明您能够将您的专业类序列化/反序列化到您的基类,因此根据定义,这更像是数据传输对象吗?我不会将逻辑放入这些中,而是引入另一个使用基类逻辑而没有继承的服务(例如将实例传递给构造函数) - 这可能首先解决了这个问题。
截至您的特定问题:如果这不是限制性的话,您可能可以使用contravariant type parameter(例如,您只能在参数中使用类型参数而不是返回类型)并且您拥有有问题的接口。但编译器只允许我以相反的方式分配服务 - 这是有道理的。也许您会以协变的方式找到解决方案吗?
{{1}}
希望这有帮助。
答案 1 :(得分:1)
简答:在IMasterService定义前缀T中用&#39; out&#39;关键字。
public interface IMasterService<out T>
{
// your existing methods' definitions here
}
它称为协方差,在MSDN中描述。