在C#中我可以将MyService <child>转换为MyService <base />吗?

时间:2017-05-30 08:54:48

标签: c# casting asp.net-core polymorphism generic-programming

背景:我们使用基于ASP.NET Core开发的基于ASP.NET Core的Web应用程序在DI&amp;通用存储库模式。因此,大多数事情都是使用接口完成的。现在,我们已经达到了主表维护模块。我们不希望为所有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. 现在所有主表都有一个控制器和服务层!

2 个答案:

答案 0 :(得分:1)

继承问题?

这种事情闻起来像你应该更喜欢构成而不是继承。由于您已经说明您能够将您的专业类序列化/反序列化到您的基类,因此根据定义,这更像是数据传输对象吗?我不会将逻辑放入这些中,而是引入另一个使用基类逻辑而没有继承的服务(例如将实例传递给构造函数) - 这可能首先解决了这个问题。

不是解决方案

截至您的特定问题:如果这不是限制性的话,您可能可以使用contravariant type parameter(例如,您只能在参数中使用类型参数而不是返回类型)并且您拥有有问题的接口。但编译器只允许我以相反的方式分配服务 - 这是有道理的。也许您会以协变的方式找到解决方案吗?

{{1}}

希望这有帮助。

答案 1 :(得分:1)

简答:在IMasterService定义前缀T中用&#39; out&#39;关键字。

public interface IMasterService<out T>
{
    // your existing methods' definitions here
}

它称为协方差,在MSDN中描述。