如何按惯例正确绑定类型?

时间:2014-05-22 18:45:18

标签: asp.net wpf dependency-injection ninject ninject-conventions

项目计划以多平台为目标,因此我在类库中提取了最多的代码,以便可以轻松地重复使用。

该架构基于Model-View-Presenter原则。

项目结构如下:

Solution
    -> Domain
    -> Domain.Tests
    -> MVP
    -> MVP.Tests
    -> Web
    -> Web.Tests
    -> Windows
    -> Windows.Tests

MVP

此项目包含演示者和项目的视图。例如:

public interface IApplicationView : IView, IHasUiHandler<IApplicationUiHandler> {
}

public class ApplicationPresenter : Presenter<IApplicationView>
    , IApplicationUiHAndler {
    public ApplicationPresenter(IApplicationView view) : base(view) {
        View.Handler = this;
    }
}

该项目包含应用程序的WPF GUI和所谓的Composition Root。例如:

public class ApplicationWindow : Window, IApplicationView {
}

public class App : Application {
    protected override void OnStartUp(StartupEventArgs e) {
        IKernel kernel = new StandardKernel();
        kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses().EndingWith("Window")
            .BindAllInterfaces().EndingWith("View") // Here's what I'd like to do.
        );
    }
}

网络

此项目包含应用程序的ASP.NET GUI页面和所谓的Composition Root。

public class ApplicationPage : Page, IApplicationView {
}

public class MvcApplication : HttpApplication {
    protected override void Application_Start() {
        IKernel kernel = new StandardKernel();
        kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses().EndingWith("Page")
            .BindAllInterfaces().EndingWith("View") // Here's what I'd like to do.
    }
}

嗯,我想你明白了......

我对依赖注入很新,甚至更新于约定。

我想知道如何使用Ninject使用约定来配置绑定。

知道如何用Windows(WPF)和Pages(Web)绑定这些视图吗?

  

修改

在尝试了@BatteryBackupUnit建议之后,我想我的问题就是我对程序集的搜索。

using (var kernel = new StandardKernel()) 
    kernel.Bind(scanner => scanner
        .From(AppDomain.CurrentDomain
            .GetAssemblies()
            .Where(a => (a.FullName.Contains("MyProject.MVP") 
                || a.FullName.Contains("Windows"))
                && !a.FullName.Contains("Tests")))
        .SelectAllClasses()
        .EndingWith("Window")
        .BindSelection((type, baseType) =>
            type.GetInterfaces().Where(iface => iface.Name.EndsWith("View"))));

如前所述,View接口与Window类不在同一个程序集中。上面的代码基于@ BatteryBackupUnit的答案,效果很好。

1 个答案:

答案 0 :(得分:1)

这个怎么样:

using FluentAssertions;
using Ninject;
using Ninject.Extensions.Conventions;
using System.Linq;
using Xunit;

public interface ISomeView { }
public interface ISomeOtherView { }
public interface INotEndingWithViewWord { }

public class SomePage : ISomeView, ISomeOtherView, INotEndingWithViewWord
{
}

public class Demo
{
    [Fact]
    public void Test()
    {
        using (var kernel = new StandardKernel())
        {
            kernel.Bind(x => x
                .FromThisAssembly()
                .SelectAllClasses()
                .EndingWith("Page")
                .BindSelection((type, baseType) => 
                     type.GetInterfaces()
                     .Where(iface => iface.Name.EndsWith("View"))));

            kernel.Get<ISomeView>().Should().BeOfType<SomePage>();

            kernel.Get<ISomeOtherView>().Should().BeOfType<SomePage>();

            kernel.Invoking(x => x.Get<INotEndingWithViewWord>())
                .ShouldThrow<ActivationException>();
        }
    }
}

注意:我一直在使用nuget包

  • Ninject
  • Ninject.Extensions.Conventions
  • xunit.net
  • FluentAssertions

那些xunit.net和FluentAssertions仅用于运行测试而不用于生产。

或者您也可以使用.BindWith<T : IBindingGenerator>.BindUsingRegex(...)