如何解决多层构造函数注入问题

时间:2013-04-19 17:45:27

标签: asp.net-mvc asp.net-mvc-3 ninject

在我的项目中,我对IRepositoryProvider等有一个控制器依赖。

public class HomeController : BaseController
{
    public HomeController(ISessionWrapper sessionWrapper,
                          IRepositoryProvider repositoryProvider,
                          IApplicationConfiguration applicationConfiguration)
        : base(sessionWrapper, repositoryProvider, applicationConfiguration)
    {}

    ...

}

IRepositoryProvider及其实现存在于BLL层中。另外需要注意的是,IRepositoryProvider也有一些参数。这些用于确定要使用的连接字符串(Environment * 5可能的连接)。

    public RepositoryProvider(string environment, IApplicationConfiguration applicationConfiguration)
    {
        _applicationConfiguration = applicationConfiguration;
        _environment = environment;
    }

这一切都适用于两层和这个Ninject配置。

kernel.Bind<IRepositoryProvider>()
      .To<RepositoryProvider>()
      .InRequestScope()
      .WithConstructorArgument("environment",    
                                context => context.Kernel.Get<ISessionWrapper>().CurrentEnvironment)
      .WithConstructorArgument("applicationConfiguration",
                                context => context.Kernel.Get<IApplicationConfiguration>());

当我介绍服务层时,我的问题就出现了。我希望使用服务层,而不是依靠我的控制器中的IRepositoryProvider进行数据访问。理想情况下,我不想引用BLL层,只引用服务层。

public class HomeService : IHomeService
{
    public IRepositoryProvider RepositoryProvider { get; private set; }

    public HomeService(IRepositoryProvider repositoryProvider)
    {
        RepositoryProvider = repositoryProvider;
    }
    ...
}

所以我的问题是:我是否可以不参考MVC项目中的Service和BLL层?或者这整个设置是一个巨大的代码味道?

感谢。

更新:我想我应该说出我理想的参考资料。网络 - &gt;服务 - &gt; BLL。目前,Web引用了Service和BLL,以便Ninject解决所有问题。

更新2:这看起来像是一个可能的解决方案吗? How to tell Ninject to bind to an implementation it doesn't have a reference to

2 个答案:

答案 0 :(得分:3)

这就是我通常根据需求设计MVC项目的方式。

表示层&gt;服务层&gt;业务层&gt;数据访问层。

表示层包含:ViewModels,Views,Controllers。 (参考服务层,Ninject ddl)

服务层:WCF。 (参考BAL等)

业务层:包含我称之为Orchestrators及其接口(参考DAL,域)

数据访问层:包含存储库及其接口(引用域)

域:包含POCO对象

核心:我实际安装和配置Ninject的地方(参考BAL,DAL等)

将Ninject添加到演示层以外的另一个项目:

将以下内容添加到Global.Asasx.cs:

DependencyResolver.SetResolver(new NinjectDependencyResolver());

然后创建一个新项目sucche作为核心。在那里安装Ninject并添加以下类:

您需要从表示层

引用Ninject dll
 public class NinjectDependencyResolver : IDependencyResolver {
    private IKernel kernel;

    public NinjectDependencyResolver() 
    {
        kernel = new StandardKernel();
        AddBindings();
    }

    public object GetService(Type serviceType) 
    {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) 
    {
        return kernel.GetAll(serviceType);
    }

    public IBindingToSyntax<T> Bind<T>() 
    {
        return kernel.Bind<T>();
    }

    public IKernel Kernel 
    {
        get { return kernel; }
    }

    private void AddBindings() 
    {
        //Add your Bindings here
    }

}

答案 1 :(得分:2)

  

IRepositoryProvider及其实现存在于BLL层中......   我是否可以不引用Service和BLL层   来自MVC项目

根据你的这两个陈述,答案是 NO ,你不可能“不”引用这些层。最小化引用的最佳方法是将接口与实现分开。例如,您可以拥有以下内容:

域名层,包含您的POCO和界面

  • 产品(样本类)
  • IRepository(界面)

服务层,包含接口的实现

  • 引用Domain图层
  • 实施IRepository(例如ProductRepository : IRepository

依赖注入层

  • 了解DomainService图层

MVC项目

  • 引用Domain图层以了解POCO和存储库签名
  • 引用DI图层,但不知道它是如何确切的 作品。所以你可以稍后换掉DI框架,一切都会有效。

您可以根据需要展开该图层。您可以在BLLDomain图层之间插入Service图层,但不需要在任何地方引用它。