问题非常技术性,它深深地介于F#/ C#差异之间.我很可能错过了一些东西.如果您发现概念错误,请发表评论,我将更新问题.
让我们从C#世界开始吧.假设我有一个简单的业务对象,请调用它Person(但是,请记住,有100多个对象远比我们使用的业务领域中的对象复杂得多):
public class Person : IPerson
{
public int PersonId { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我使用DI/IOC,所以我从来没有实际传Person过来.相反,我总是使用一个接口(如上所述),称之为IPerson:
public interface IPerson
{
int PersonId { get; set; }
string Name { get; set; }
string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
业务要求是可以从数据库序列化/反序列化该人员.假设我选择使用Entity Framework,但实际的实现似乎与问题无关.此时我可以选择引入"数据库"相关类,例如EFPerson:
public class EFPerson : IPerson
{
public int PersonId { get; set; }
public string …Run Code Online (Sandbox Code Playgroud) 如果我在Visual Studio F#项目中双击源文件并意外地略微移动鼠标(即几个像素就足够了),则VS将文件"重命名"为副本.
例如文件SomeSource.fs变为Copy of SomeSource.fs.此时的原始文件"消失",并在项目结束时添加副本.问题发生在我使用的所有计算机上,仅在F#中,而不是在C#中.
似乎在VS中应该有一些设置,它告诉它这样做.如何禁用那个东西?
谢谢.
这个问题基于一个很棒的F#/ DI相关帖子:https://fsharpforfunandprofit.com/posts/dependency-injection-1/
我试着在那里发布问题.但是,由于网站上的一些故障,似乎无法再注册帖子.所以,这里是:
我想知道该帖子中描述的场景将如何工作/转化为更真实的例子.下面的数字是从天空稍微有点,所以,请在需要时调整它们.
考虑一些相当小的基于C#的DI/TDD/EF Code First项目:
组合根:20个接口,每个接口有10个方法(平均).好吧,这可能是每个接口的方法太多,但不幸的是,随着代码的发展,它们往往会膨胀.我见过更多.其中10个是没有任何IO的内部服务(func世界中没有数据库/"纯"函数),5个是内部IO(本地数据库和类似),最后5个是外部服务(如外部数据库) s)或其他任何调用某些远程第三方服务的东西).
每个接口都有一个生产级实现,具有4个注入接口(平均),并且每个接口使用5个成员,每个实现使用的总共20个方法(平均).
有几个级别的测试:单元测试,集成测试(两个级别),验收测试.
单元测试:使用适当的模拟设置(使用一些标准工具,例如Moq)模拟所有调用.因此,至少有20*10 = 200个单元测试.通常还有更多,因为测试了几种不同的场景.
集成测试(级别1):所有没有IO的内部服务都是真实的,所有内部IO相关服务都是假货(通常是内存数据库),所有外部服务都代理一些假货/模拟.基本上这意味着所有内部IO服务,如SomeInternalIOService:ISomeInternalIOService被FakeSomeInternalIOService取代:ISomeInternalIOService和所有外部IO服务,如SomeExternalIOService:ISomeExternalIOService被FakeSomeExternalIOService:ISomeExternalIOService取代.因此,有5个虚假的内部IO和5个虚假的外部IO服务,并且测试次数与上述相同.
集成测试(级别2):所有外部服务(包括现在与本地数据库相关的服务)都是真实的,所有外部服务都代理到其他一些假货/模拟,这允许测试外部服务的故障.基本上这意味着所有外部IO服务,如SomeExternalIOService:ISomeExternalIOService被BreakableFakeSomeExternalIOService:ISomeExternalIOService取代.有5种不同的(易碎的)外部IO假服务.假设我们有大约100个这样的测试.
验收测试:一切都是真实的,但配置文件指向外部服务的某些"测试"版本.假设大约有50个这样的测试.
我想知道这将如何转化为F#世界.显然,很多事情都会有很大不同,有些事情甚至可能不存在于F#世界!
非常感谢!
PS我不是在寻找确切的答案.有一些想法的"方向"就足够了.
从某种意义上说,这等效于TheoryData,但应用于测试类级别而不是方法级别。在当前的 XUnit 框架内这可能吗?如果是,那么具体如何?
我想关闭Entity Framework Core(我说的是 EF Core 5 或更高版本)中的所有(或至少大部分)约定,然后“手动”构建整个模型。
人们可能想知道为什么。
原因如下:我有一项任务,将多个大型遗留数据库从 Entity Framework 6 ( EF) 迁移到 Entity Framework Core 5 ( EFC)。这涉及数百个表和多个数据库。其中一些数据库是使用 Code First 方法创建的,有些只是第三方数据库,我们需要从 C# 代码查询和更新。对于后面的数据库,我们必须完全匹配它们的模式。
由于问题的规模,代码的风格EF和EFC风格必须共存,比如说,几个月。这可以通过使用条件编译轻松实现(见下文)。
最有可能的是不支持或不方便支持(或被“侵入”到模型中)的任何内容,EFC例如空间索引、多列PK、多列FK、自引用多个乘法表、定义的多个索引相同的列(有些是过滤器,有些只是常规索引),依此类推。EFEFKeyAttributeForeignKeyAttribute
没关系。我可以通过使用条件编译“覆盖”属性来轻松处理EFC 无法处理的问题,例如
#if EFCORE
using Key = MyKeyAttribute;
using Column = MyColumnAttribute;
using Index = MyIndexAttribute;
using ForeignKey = MyForeignKeyAttribute;
#endif
Run Code Online (Sandbox Code Playgroud)
然后为每个MyProject.csproj创建一个定义的MyProject_EFC.csproj位置EFCORE,然后使用反射来“收集”所有这些自定义属性,然后使用EFCFluent API 来配置所有EFC无法执行的操作。因此,遗留 ( …
我有以下Unity相关问题.下面的代码存根设置基本方案,问题位于底部.
注意,该[Dependency]属性不适用于下面的示例并导致StackoverflowException,但构造函数注入确实有效.
注意(2)下面的一些评论开始分配"标签",如代码气味,糟糕的设计等......因此,为了避免混淆,这里是没有任何设计的业务设置.
这个问题似乎引起了一些最着名的C#大师的严重争议.事实上,这个问题远远超出了C#,它更多地涉及纯粹的计算机科学.问题是基于服务定位器模式和纯依赖注入模式之间众所周知的"战斗":https://martinfowler.com/articles/injection.html vs http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern /以及后续更新以解决依赖注入过于复杂时的情况:http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
这是一种情况,它不能很好地适应前两种情况,但似乎完全符合第一种情况.
我有一个大的(50+)集合,我称之为微服务.如果您有更好的名字,请在阅读时"申请".它们中的每一个都在一个对象上运行,我们称之为引用.但是,元组(上下文+引用)似乎更合适.Quote是一个业务对象,它被处理并序列化为数据库,上下文是一些支持信息,这在处理报价时是必要的,但不保存到数据库中.其中一些支持信息实际上可能来自数据库或某些第三方服务.这是无关紧要的.装配线作为一个现实世界的例子浮现在脑海中:装配工人(微服务)接收一些输入(指令(上下文)+部件(引用)),处理它(根据指令和/或修改指令对部件做某事)并且如果成功则将其进一步传递或在发生问题时丢弃它(引发异常).微服务最终被捆绑到少数(约5个)高级服务中.这种方法线性化了一些非常复杂的业务对象的处理,并允许将每个微服务与所有其他服务分开测试:只需给它一个输入状态并测试它产生预期的输出.
这是有趣的地方.由于涉及的步骤数量多,高级服务开始依赖于许多微服务:10+以上.这种依赖性很自然,它只反映了底层业务对象的复杂性.最重要的是,微服务几乎可以在不断的基础上添加/删除:基本上,它们是一些业务规则,几乎像水一样流畅.
这与Mark上面的建议严重冲突:如果我在一些高级服务中有10个以上有效的独立规则应用于某个高级服务的引用,那么,根据第三个博客,我应该将它们聚合成一些逻辑组,比如说不超过3-4而不是注入所有10+通过构造函数.但是没有合乎逻辑的团体!虽然有些规则是松散依赖的,但大多数规则都没有,因此人为地将它们捆绑在一起会带来更多弊大于利.
抛出规则经常变化,它变成了维护的噩梦:每次规则改变时,所有真实/模拟的呼叫都必须更新.
我甚至没有提到规则是美国依赖的,因此,理论上,大约有50个规则集合,每个州和每个工作流程都有一个集合.虽然一些规则在所有州之间共享(例如"保存对数据库的引用"),但是有很多州的具体规则.
这是一个非常简单的例子.
引用 - 业务对象,它被保存到数据库中.
public class Quote
{
public string SomeQuoteData { get; set; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
微服务.他们每个人都会执行一些小的更新来引用.也可以从一些较低级别的微服务构建更高级别的服务.
public interface IService_1
{
Quote DoSomething_1(Quote quote);
}
// ...
public interface IService_N
{
Quote DoSomething_N(Quote quote);
}
Run Code Online (Sandbox Code Playgroud)
所有微服务都继承自此接口.
public interface IQuoteProcessor
{
List<Func<Quote, Quote>> QuotePipeline { get; }
Quote ProcessQuote(Quote quote = null);
}
// Low …Run Code Online (Sandbox Code Playgroud) 我只是在尝试在 VS 15.8.1 下配置 F# 4.5.0.0 来运行 xUnit 测试时遇到了困难。这是有问题的 repo:https : //github.com/kkkmail/fSharp-xUnit。当我尝试运行所有测试时,VS 返回此消息:C:\GitHub\fSharp-xUnit\DummyApp\DummyApp\bin\Debug\DummyApp.exe C:\GitHub\fSharp-xUnit\DummyApp 中没有可用的测试\Tests\bin\Debug\Tests.dll C:\GitHub\fSharp-xUnit\DummyApp\DummyApp\DummyApp.fsproj C:\GitHub\fSharp-xUnit\DummyApp\Tests\Tests.fsproj。确保测试发现者和执行者已注册,平台和框架版本设置适当,然后重试。
“DummyApp”和测试都是使用 VS 从头开始创建的,我在创建解决方案之前清除了所有临时文件和所有 nuget 缓存,如网络上不同位置的建议。
我有一些科学项目.那里有各种长度的矢量/方形矩阵.显然(例如)长度为2的向量不能添加到长度为3的向量中(依此类推).有几个.NET库,它们处理向量/矩阵.所有这些都有通用的载体/矩阵或者有一些非常特殊的载体/矩阵,它们不能满足需要.
大多数(如果不是全部)这些库可以从列表或数组创建向量.不幸的是,如果我错误地给出了一个错误长度的输入数组,那么我将得到一个错误长度的向量,然后一切都会在运行时爆炸!
我想知道是否有可能在编译时检查数组长度,以便得到编译错误,如果,让我们说,我尝试将5元素数组传递给长度为2"构造函数"的向量.毕竟,printfn几乎就是这样!
我想到了F#类型的提供商,但我不确定如何在这里应用它们.
非常感谢!
我们使用一些扩展方法,它们允许我们编写类似的东西:
.Single(e => $"{nameof(SomeParameter)}: {SomeParameter}, ...")
Run Code Online (Sandbox Code Playgroud)
而不仅仅是
.Single()
Run Code Online (Sandbox Code Playgroud)
哪里e是例外.
这大大增加了日志记录体验,因为上层变量记录所有参数而不是无用的"序列不包含任何元素",这是底层产生的.
我需要编写一个测试,它会找到所有不兼容的代码,例如调用.Single().
当然,我可以使用正则表达式搜索或只是简单的香草文本搜索来查找从解决方案根开始的所有CS文件,也许这是可行的方法.我只是想知道是否已经有一个简单而已知的解决方案.
这就是我需要的:
轻松添加/删除规则:例如,查找所有文件,找到所有文件但不.Single()具有.Single(的形式.Single(e => $"- 这是考虑到组合的Where + Single代码等...
测试应该从xUnit运行.
非常感谢!