C# 当需要设计模块化架构时,对象投射是现实的必然吗?
人们普遍认为,物体投射是一种不好的做法,应该避免,例如,问题已经得到了一些答案,并且有很大的争议:C# 当需要设计模块化架构时,对象投射是现实的必然吗?,c#,oop,casting,solid-principles,autofixture,C#,Oop,Casting,Solid Principles,Autofixture,人们普遍认为,物体投射是一种不好的做法,应该避免,例如,问题已经得到了一些答案,并且有很大的争议: 从更广泛的角度来看,情况相当简单(至少) 一个演员阵容(显然足够)意味着你正在转化 从一种类型到另一种类型的东西。如果你这样做,它会引起 问“为什么?”如果你真的想让某样东西成为一种特殊类型, 你为什么不先把它定义为那种类型?这是不可能的 说从来没有理由做这样的转换,但任何时候都可以 如果发生这种情况,它会提示您是否可以重新设计 代码,以便始终使用正确的类型 : 这两种类型的演员都是危险信号。
第二种类型的演员阵容提出了一个问题:“为什么不进行手术?” 首先在目标数据类型中执行?”如果需要 一个整数的结果,那么为什么你在第一个整数中持有一个双精度 地点?你不应该拿着一个int吗
object Create(object request, ISpecimenContext context);
正如您所看到的,请求参数类型是object,因此它接受完全不同的类型,接口的不同实现按运行时类型处理不同的请求,检查它们是否正在处理某个请求,否则将返回某种无响应表示
界面的设计似乎不符合“良好实践”,即对象浇铸应该很少使用
我在想,是否有更好的方法来设计这份合同,使所有演员都失败,但找不到任何解决办法。显然,对象参数可以用一些标记接口来替换,但这并不能解决铸造问题,我还认为可以使用所描述的访客模式的一些变体,但它似乎不是非常可扩展,访问者必须有几十种不同的方法,因为接口有很多不同的实现,能够处理不同类型的请求 虽然我基本上同意反对在这个特定场景中使用铸造作为良好设计的一部分的观点,但它似乎不仅是最好的选择,也是唯一现实的选择
总之,当需要设计模块化和可扩展的体系结构时,对象投射和非常一般的契约是否是现实的必然 对于任何类型的应用程序或框架,我都不认为我可以笼统地回答这个问题,但我可以提供一个专门讨论AutoFixture的答案,以及对其他使用场景的一些推测 如果我今天必须从头开始编写AutoFixture,我肯定会做一些不同的事情。特别是,我不会围绕
ISpecimenBuilder
这样的东西来设计日常API。相反,我将围绕函子和单子的概念来设计数据操作API,如下所示
这种设计完全基于泛型,但它确实需要编译时已知的静态类型构建块(本文中也有描述)
这与类似的工作方式密切相关。编写基于快速检查的测试时,必须为所有自定义类型提供生成器。Haskell不支持运行时强制转换值,而是完全依赖于泛型和一些编译时自动化。诚然,Haskell的泛型比C#的更强大,因此您不一定能将从Haskell获得的知识转移到C#。然而,它确实表明,完全不依赖运行时强制转换就可以编写代码
但是,AutoFixture支持用户定义的类型,而无需用户编写自定义生成器。它是通过.NET反射实现的。在.NET中,反射API是非类型化的;所有生成对象和调用成员的方法都将object
作为输入,并将object
作为输出返回
任何基于反射的应用程序、库或框架都必须执行一些运行时强制转换。我不知道该怎么解决这个问题
是否可以在没有反射的情况下编写数据生成器?我没有尝试过下面的方法,但也许可以采用一种策略,直接在IL中为数据生成器编写“代码”,并使用反射发射动态编译包含生成器的内存程序集
这有点像它的工作原理,IIRC。我想人们可以围绕这个概念设计其他类型的通用框架,但我很少看到它在.NET中实现。这个问题,就像您链接到的问题一样,可能太广泛了。我想你可能会更好,但首先检查他们的常见问题(我不是100%确定)。答案是在报价真的
这并不是说没有理由进行这样的转换,但无论何时,它都会提示您是否可以重新设计代码,以便始终使用正确的类型。
从另一个问题的答案中,您可以回答自己的问题,这取决于您的设计以及如何创建模块化和可扩展的体系结构。你可以