小编Tea*_*Dev的帖子

F#中的应用程序架构/组合

我最近在C#中将SOLID做到了非常极端的水平,并且在某些时候意识到我现在基本上没有做太多的事情.在我最近再次开始研究F#之后,我认为对于我现在正在做的很多事情,它可能是更合适的语言选择,所以我想尝试将一个真实的C#项目移植到F#作为概念的证明.我想我可以推出实际的代码(以一种非惯用的方式),但我无法想象一个架构会是什么样的,它允许我以与C#类似的灵活方式工作.

我的意思是我有很多小类和接口,我使用IoC容器编写,我也使用了像Decorator和Composite这样的模式.这导致(在我看来)非常灵活和可演化的整体架构,使我能够在应用程序的任何位置轻松替换或扩展功能.根据所需更改的大小,我可能只需要编写一个新的接口实现,在IoC注册中替换它并完成.即使更改更大,我也可以替换部分对象图,而应用程序的其余部分只是像以前一样.

现在使用F#,我没有类和接口(我知道我可以,但我认为这与我想要进行实际函数式编程的时间不同),我没有构造函数注入,而且我没有IoC容器.我知道我可以使用更高阶函数做类似Decorator模式的东西,但这似乎并没有给我带有构造函数注入的类的灵活性和可维护性.

考虑这些C#类型:

public class Dings
{
    public string Lol { get; set; }

    public string Rofl { get; set; }
}

public interface IGetStuff
{
    IEnumerable<Dings> For(Guid id);
}

public class AsdFilteringGetStuff : IGetStuff
{
    private readonly IGetStuff _innerGetStuff;

    public AsdFilteringGetStuff(IGetStuff innerGetStuff)
    {
        this._innerGetStuff = innerGetStuff;
    }

    public IEnumerable<Dings> For(Guid id)
    {
        return this._innerGetStuff.For(id).Where(d => d.Lol == "asd");
    }
}

public class GeneratingGetStuff : IGetStuff
{
    public IEnumerable<Dings> For(Guid id)
    {
        IEnumerable<Dings> dingse;

        // somehow knows how to …
Run Code Online (Sandbox Code Playgroud)

f# inversion-of-control composition solid-principles

72
推荐指数
1
解决办法
5240
查看次数

XUnit Assertion用于检查对象的相等性

我正在使用XUnit框架来测试我的C#代码.

这个框架中是否有可用于对象比较的断言方法?我的目的是检查每个对象的公共和私有成员变量是否相等.

我试过那些替代品但很少有效:

1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
Run Code Online (Sandbox Code Playgroud)

c# xunit xunit.net

24
推荐指数
6
解决办法
2万
查看次数

IoC:连接事件处理程序的依赖项

我正在构建一个WinForms应用程序,其UI只包含一个NotifyIcon动态填充的UI ContextMenuStrip.有一个MainForm共同持有的申请,但这是从来没有看见.

我开始尽可能安全地构建它(使用Autofac来处理对象图)并且对我的成功感到非常满意,即使使用O部分也相当不错.随着我目前正在实施的扩展,似乎我发现了我的设计中的一个缺陷,需要重新改造一下; 我想知道我需要去的方式但是有点不清楚如何准确定义依赖关系.

如上所述,菜单部分在启动应用程序后动态填充.为此,我定义了一个IToolStripPopulator接口:

public interface IToolStripPopulator
{
    System.Windows.Forms.ToolStrip PopulateToolStrip(System.Windows.Forms.ToolStrip toolstrip, EventHandler itemclick);
}
Run Code Online (Sandbox Code Playgroud)

将此实现注入到MainForm,并且Load()方法PopulateToolStrip()使用ContextMenuStrip表单中定义的处理程序调用.populator的依赖关系仅与获取用于菜单项的数据有关.

这个抽象通过一些进化步骤很好地工作,但是当我需要多个事件处理程序时,这已经不够了,例如因为我正在创建几个不同的菜单项组 - 仍然隐藏在单个IToolStripPopulator界面后面,因为表单不应该是完全关心这一点.

正如我所说,我想我知道一般结构应该是什么样的 - 我将IToolStripPopulator接口重命名为更具体的东西*并创建了一个新PopulateToolStrip()方法,其方法不接受EventHandler参数,而是将其注入到对象中(也允许更多关于实现所需的处理程序数量的更多灵活性等).这样,我的"最重要的" IToolStripPopulator可以很容易地成为任何数量的特定适配器的适配器.

现在我不清楚的是我应该如何解决EventHandler依赖项.我认为处理程序应该全部定义MainForm,因为它具有正确响应菜单事件所需的所有其他依赖项,并且它还"拥有"菜单.这意味着我IToolStripPopulator最终注入到MainForm中的MainForm对象的依赖关系需要依赖于对象本身Lazy<T>.

我的第一个想法是定义一个IClickHandlerSource接口:

public interface IClickHandlerSource
{
    EventHandler GetClickHandler();
}
Run Code Online (Sandbox Code Playgroud)

这是由我实现的MainForm,我的具体IToolStripPopulator实现依赖于Lazy<IClickHandlerSource>.虽然这有效,但它是不灵活的.我要么必须为可能越来越多的处理程序定义单独的接口(严重违反OCP与MainForm类)或不断扩展IClickHandlerSource(主要违反ISP).直接依赖事件处理程序在消费者方面看起来是一个好主意,但是通过惰性实例(或类似)的属性单独连接构造函数似乎非常混乱 - 如果可能的话.

我最好的打赌似乎是这样的: …

c# dependency-injection inversion-of-control winforms solid-principles

13
推荐指数
1
解决办法
2052
查看次数

AutoFixture/AutoMoq忽略注入的实例/冻结模拟

现在找到解决方案的简短内容:

AutoFixture返回冻结模拟就好了; 我的sut也是由AutoFixture生成的,只有一个公共属性,其本地默认值对于测试非常重要,并且AutoFixture设置为新值.除了Mark的答案之外,还有很多值得学习的东西.

原始问题:

我昨天开始尝试使用AutoFixture进行我的xUnit.net测试,这些测试中包含了Moq.我希望更换一些Moq的东西或者让它更容易阅读,我特别感兴趣的是在SUT工厂容量中使用AutoFixture.

我使用Mark Seemann的一些关于AutoMocking的博客文章,并尝试从那里开始工作,但我没有走得太远.

这是我的测试看起来没有AutoFixture:

[Fact]
public void GetXml_ReturnsCorrectXElement()
{
    // Arrange
    string xmlString = @"
        <mappings>
            <mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
            <mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
        </mappings>";

    string settingKey = "gcCreditApplicationUsdFieldMappings";

    Mock<ISettings> settingsMock = new Mock<ISettings>();
    settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
    ISettings settings = settingsMock.Object;

    ITracingService tracing = new Mock<ITracingService>().Object;

    XElement expectedXml = XElement.Parse(xmlString);

    IMappingXml sut = new SettingMappingXml(settings, tracing);

    // Act
    XElement actualXml = sut.GetXml();

    // Assert
    Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
Run Code Online (Sandbox Code Playgroud)

这里的故事很简单 - 确保使用正确的密钥(这是硬编码/属性注入)SettingMappingXml查询ISettings依赖关系并将结果返回为XElement.在 …

c# unit-testing autofixture automocking

11
推荐指数
1
解决办法
3719
查看次数

TinyIoC:在单个实例上注册多个接口

Autofac允许使用.AsImplementedInterfaces()或链接非常容易地将多个接口解析到同一个实例.As <>()与.SingleInstance()一起调用.这也可以用TinyIoC完成吗?我只发现了如何注册同一个接口的多个实现,但没有办法链接注册等.

根据我的理解,这是IoC容器的一个非常重要的功能,不是吗?

.net inversion-of-control tinyioc

9
推荐指数
1
解决办法
1532
查看次数

为什么`DefaultNancyBoostrapper`找不到我的NancyModule

我只是在南希弄湿了脚.我很高兴看到Wiki中的测试过程,但是当我尝试以下操作时,我无法通过测试来完成测试.

使用VS2010

  1. 创建Empty ASP.NET Web Application Project:Notify.App
  2. Install-Package Nancy.Hosting.AspNet
  3. 创建简单模块,如下所示:NotifyModule
  4. 创建Class Library项目:Notify.UnitTests
  5. Install-Package Nancy.Testing
  6. Install-Package XUnit
  7. 创建简单的第一个测试:BaseUrlSpec.cs

使用DefaultNancyBootstrapper测试失败了HttpStatusCode.NotFound.

如果我用以下内容替换bootstrapper定义:

var bootstrapper = new ConfigurableBootstrapper(
                          with => 
                             with.Module<NotifyModule>());
Run Code Online (Sandbox Code Playgroud)

然后测试通过. 我不明白为什么使用DefaultNancyBootstrapper的SDHP不起作用?我做错了什么让它破裂,还是我在理解中遗漏了细节?


NotifyModule

using Nancy;
public class NotifyModule : NancyModule {
    public NotifyModule() {
        Get["/"] = _ => HttpStatusCode.OK;
    }
}
Run Code Online (Sandbox Code Playgroud)

BaseUrlSpec

using Nancy;
using Nancy.Testing;
using Notify.App;
using Xunit;
public class BaseUrlSpec
{
    [Fact]
    public void ShouldRespondOk()
    {
        var bootstrapper = new …
Run Code Online (Sandbox Code Playgroud)

unit-testing nancy

8
推荐指数
1
解决办法
2243
查看次数

AutoFixture使用手动假货的AutoData理论

鉴于此系统要测试:

public class MySut
{
    private readonly IHardToMockDependency _hardToMockDependency;

    public MySut(IHardToMockDependency hardToMockDependency,
                 IOtherDependency otherDependency)
    {
        _hardToMockDependency = hardToMockDependency;
    }

    public string GetResult()
    {
        return _hardToMockDependency.GetResult();
    }
}

public interface IOtherDependency { }

public interface IHardToMockDependency
{
    string GetResult();
}
Run Code Online (Sandbox Code Playgroud)

而这个单元测试:

internal class FakeHardToMockDependency : IHardToMockDependency
{
    private readonly string _result;

    public FakeHardToMockDependency(string result)
    {
        _result = result;
    }

    public string GetResult()
    {
        return _result;
    }
}

public class MyTests
{
    [Fact]
    public void GetResultReturnsExpected()
    {
        string expectedResult = "what I …
Run Code Online (Sandbox Code Playgroud)

moq xunit.net autofixture automocking

7
推荐指数
1
解决办法
2624
查看次数

Default和[Optional]参数有什么区别?

有什么区别

Method(int arg0 = 0) vs Method([Optional] int arg0 = 0);
Run Code Online (Sandbox Code Playgroud)

每当我试图调用这个方法时,编译器就会说出它的模糊情况.我知道为什么它是模棱两可的情况,我的兴趣是那两个如果他们促进相同的事情=可选参数之间的差异.然而,他们以不同的方式这样做,在视觉上清单 - 不知道引擎盖下.

有人向我指出,第一种方式实际上是DEFAULT使用,这意味着你将初始化默认值,而第二种方式是可选的,它用于你不定义任何默认值的情况 - 虽然它有意义,但它们都可以很容易分配值而不是.它们的真正区别和用途是什么?

c#

7
推荐指数
1
解决办法
1181
查看次数

使用Simple Injector注入MVC​​ Controller Constructor时未注册参数

我有一个非常基本的问题,使用Simple Injector将依赖项注入MVC​​控制器.我以前使用过SimpleMap的Simple Injector.

MVC的版本是4.5,它是从NuGet安装的Simple Injector的最新版本.

查看HomeController的/ Index视图时出现的错误是:

HomeController类型的构造函数包含IContext类型的参数,其名称为"context",未注册.请确保IContext已在容器中注册,或更改HomeController的构造函数.

控制器如下:

public class HomeController : Controller
{
    public HomeController(IContext context) { }

    public ActionResult Index() { }
}
Run Code Online (Sandbox Code Playgroud)

IContext只是一个简单的界面:

public interface IContext
{
}
Run Code Online (Sandbox Code Playgroud)

具体的IContext实现也很简单,只是常规DbContext的包装器.

public class DbContext : System.Data.Entity.DbContext, IContext
{ 

}
Run Code Online (Sandbox Code Playgroud)

有关信息,IContext接口与DbContext实现位于不同的VS Project/Assembly中.这些由MVC项目引用.

我在Global.asax.cs中有以下内容:

protected void Application_Start()
{
    var container = new Container();

    container.Register<IContext, DbContext>();

    container.RegisterMvcControllers(System.Reflection.Assembly.GetExecutingAssembly());

    container.RegisterMvcAttributeFilterProvider();

    container.Verify();

    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

    // Regular MVC startup
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Run Code Online (Sandbox Code Playgroud)

这是堆栈跟踪:

[ActivationException: The constructor of the type HomeController contains the …
Run Code Online (Sandbox Code Playgroud)

c# asp.net-mvc dependency-injection simple-injector asp.net-mvc-4

7
推荐指数
1
解决办法
8044
查看次数

根据函数的位置键入与泛型相关的错误

ofType<'T>基于以下方式为序列创建了一个可管道的函数Enumerable.OfType<'T>():

let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)

在同一个.fsx文件中使用它可以正常工作; 我把它放入模块时仍然会这样做:

module Seq =
    let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)

当我将其移动到另一个脚本文件中时(它能够从其他地方访问它)将它包装在另一个顶级模块中时它停止工作:

module Prelude =
    open System.Linq

    module Seq =
        let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)

我从原始脚本文件中引用它,打开Prelude模块并调用函数如下:

let getXmlIncludes (xtype : Type) =
    xtype.GetCustomAttributes() |> Seq.ofType<XmlIncludeAttribute>
Run Code Online (Sandbox Code Playgroud)

这导致Seq.ofType<XmlIncludeAttribute>被标记为错误,带有消息

error FS0001: Type mismatch. Expecting a
    Collections.Generic.IEnumerable<Attribute> -> 'a    
> but given a
    Collections.Generic.IEnumerable<Attribute> -> Collections.Generic.IEnumerable<XmlIncludeAttribute>    
The type 'obj' does …
Run Code Online (Sandbox Code Playgroud)

generics f#

7
推荐指数
1
解决办法
154
查看次数