【发布时间】:2017-05-30 08:54:48
【问题描述】:
背景:我们有一个基于 ASP.NET Core 的 Web 应用程序,它使用基于 DI 和通用存储库模式开发的 EF Core。因此,大多数事情都是使用接口完成的。现在,我们已经到了主表维护模块。我们不想为所有 10-20 个主表复制相同的服务(由存储库支持)类。
因此,我们创建了一个_ModelMasterBase 类并从中派生了所有主表类。所有主表的 CRUD 都是相同的。所以,接下来我们实现了MasterRepository<T>、MasterService<T> 和它们的接口。现在一切都必须使用<T> 其中T 是页面上选择的主表的类型来执行CRUD。
最初,我希望IMasterService<_ModelMasterBase> 的实例可以转换为 IMasterService<T>
- 再次,T 可以是任何子类 派生 从 _ModelMasterBase - 但这似乎是不可能的! 我已经尝试过运算符、强制转换以及几乎所有我可以用谷歌搜索的东西!同样由于存储库模式,所有内容都必须是强类型的。
现在,我们已经按照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. 现在所有主表都有一个控制器和服务层!
【问题讨论】:
-
这不起作用的常见例子是
List<string>。如果您可以将其转换为List<object>,那么任何人都可以将 anything 添加到列表中,这肯定会混淆任何期望List<string>只能包含strings 的代码。跨度> -
同意,但就我而言,我们想知道是否有办法以某种方式实现它 - 知道确切的装箱和拆箱场景。就像我们可以做的那样 - List<_modelbasemaster> result = data.Cast<_modelbasemaster>().ToList(); - 其中 data 可以是 List
并且 T 派生自 _ModelBaseMaster。
标签: c# casting asp.net-core polymorphism generic-programming