C# 注射清洁度

C# 注射清洁度,c#,asp.net-mvc,dependency-injection,ninject,C#,Asp.net Mvc,Dependency Injection,Ninject,好的,我正在寻找一些关于依赖注入和如何使用它的具体提示 基本上,我有一个使用Ninject(和Ninject MVC包)的MVC网站。因此,当我创建MVC页面时,我在控制器中使用构造函数注入。这没关系,但我觉得有点“难看”,但我不喜欢的主要事情是必须将所有注入的存储库传递到其他类中,这似乎有点像必须将6个存储库-8个存储库传递到静态方法或对象构造函数中 更不用说,在我的一些页面上,我必须处理几乎所有的存储库,因此控制器构造器变得庞大而不是最易于管理的 有没有其他选项不会让我的代码变得如此混乱?我

好的,我正在寻找一些关于依赖注入和如何使用它的具体提示

基本上,我有一个使用Ninject(和Ninject MVC包)的MVC网站。因此,当我创建MVC页面时,我在控制器中使用构造函数注入。这没关系,但我觉得有点“难看”,但我不喜欢的主要事情是必须将所有注入的存储库传递到其他类中,这似乎有点像必须将6个存储库-8个存储库传递到静态方法或对象构造函数中

更不用说,在我的一些页面上,我必须处理几乎所有的存储库,因此控制器构造器变得庞大而不是最易于管理的

有没有其他选项不会让我的代码变得如此混乱?我也不想将它们作为单个“设置”对象传递,因为这只是将问题转移到另一行代码中

对于控制台/桌面应用程序,我也使用相同的类库。我喜欢在类库中使用DependencyResolver.Current的想法,但每个人都说这是反模式的,应该使用构造函数注入

也许有一个MyProjectDIContext类,它有一个字典,我可以用控制器构造函数中注入的类型填充它,然后根据需要将上下文传递给所有方法


我已经找到了答案,但似乎找不到合适的答案。

构造函数注入的一个优点是它使设计和可维护性问题更加明显。当使用构造函数注入时,很容易看到一个类拥有的依赖项的数量,而没有构造函数注入,一个类仍然拥有相同数量的依赖项,但它们被隐藏起来了

您看到的问题被称为设计问题,因为它表明您违反了(SRP)。SRP指导保持类的小型化、集中化,最重要的是:可维护性

有没有其他选项不会让我的代码变得如此混乱

绝对正确:小班上课。当我们使用MVC对某个概念的方法进行分组时,比如“客户”或“订单”,MVC控制器通常会变得非常庞大。然而,这意味着控制器是一个不断增长的类,对于任何新特性都必须进行更改。这违反了我们应该努力建立一个系统,在这个系统中,我们可以在不接触现有类的情况下插入新特性


因此,解决方案不是恢复到或属性注入,而是创建完成某一特定任务的较小类。构造函数注入应该是应用依赖项注入的主要方式,即使在类库中也是如此。

控制器似乎正在将存储库转移到其他类。让Ninject为您提供这些类:

public class Controller
{
    public Controller(IDependencyFactory dependency) { }
}

public interface IDependencyFactory
{
    IDependency CreateDependency();
}

public interface IDependency
{
}

public class Dependency : IDependency
{
    public Dependency() { }
}

public class Program
{
    public static void Main()
    {
        var standardKernel = new StandardKernel();
        standardKernel.Bind<IDependencyFactory>().ToFactory();
        standardKernel.Bind<IDependency>().To<Dependency>();
    }
}
公共类控制器
{
公共控制器(IDependencyFactory依赖项){}
}
公共接口IDependencyFactory
{
IDependency CreateDependency();
}
公共接口独立性
{
}
公共类依赖:IDependency
{
公共依赖项(){}
}
公共课程
{
公共静态void Main()
{
var standardKernel=新的standardKernel();
standardKernel.Bind().ToFactory();
standardKernel.Bind().To();
}
}

您不必编写由工厂扩展处理的
IDependencyFactory
的实现。你的
依赖项
-类将获得Ninject注入的依赖项。

好的,我似乎找到了一种方法来实现这一点,但看起来没有那么臭

我曾认为,如果您使用MVC,您将通过构造函数获得存储库,这是解决依赖关系的唯一方法

在做了一些工作将可重用代码的部分移动到IoC友好的接口及其实现中之后,我注意到,当您在控制器构造函数中创建引用IMyInterface时,将运行实现类的默认构造函数,您可以从中提取其他IoC类,例如解析的存储库

这可能是常识,但它确实使事情变得更加整洁,解决了我遇到的问题


范例

控制器

public IDefaultTemplateManager DefaultTemplateManager { get; set; }

public DefaultController(IDefaultTemplateManager defaultTemplateManager) {
    this.DefaultTemplateManager = defaultTemplateManager;
}

public ActionResult MyAction(FormCollection collection) {
    DefaultTemplateManager.Process("MyKeyHere");
    View();
}
IDefaultTemplateManager

public interface IDefaultTemplateManager {
    ProcessResponse Process(string UniqueKey, DefaultTemplateManagerEditMode DatabaseName, string DefaultTemplateName);
}
    public class DefaultTemplateManager : IDefaultTemplateManager {

        protected IRepository<MyEntity1> MyEntityRepo1 { get; set; }
        protected IRepository<MyEntity2> MyEntityRepo2 { get; set; }
        protected IRepository<MyEntity3> MyEntityRepo3 { get; set; }
        protected IRepository<MyEntity4> MyEntityRepo4 { get; set; }
        protected IRepository<MyEntity5> MyEntityRepo5 { get; set; }
        protected IRepository<MyEntity6> MyEntityRepo6 { get; set; }

        public DefaultTemplateManager(IRepository<MyEntity1> MyEntityRepository1, IRepository<MyEntity2> MyEntityRepository2, IRepository<MyEntity3> MyEntityRepository3, IRepository<MyEntity4> MyEntityRepository4, IRepository<MyEntity5> MyEntityRepository5, IRepository<MyEntity6> MyEntityRepository6, ) {
            this.MyEntityRepo1 = MyEntityRepository1;
            this.MyEntityRepo2 = MyEntityRepository2;
            this.MyEntityRepo3 = MyEntityRepository3;
            this.MyEntityRepo4 = MyEntityRepository4;
            this.MyEntityRepo5 = MyEntityRepository5;
            this.MyEntityRepo6 = MyEntityRepository6;
        }

        public ProcessResponse Process(string UniqueKey) {
            /* Do Work */
        }
DefaultTemplateManager

public interface IDefaultTemplateManager {
    ProcessResponse Process(string UniqueKey, DefaultTemplateManagerEditMode DatabaseName, string DefaultTemplateName);
}
    public class DefaultTemplateManager : IDefaultTemplateManager {

        protected IRepository<MyEntity1> MyEntityRepo1 { get; set; }
        protected IRepository<MyEntity2> MyEntityRepo2 { get; set; }
        protected IRepository<MyEntity3> MyEntityRepo3 { get; set; }
        protected IRepository<MyEntity4> MyEntityRepo4 { get; set; }
        protected IRepository<MyEntity5> MyEntityRepo5 { get; set; }
        protected IRepository<MyEntity6> MyEntityRepo6 { get; set; }

        public DefaultTemplateManager(IRepository<MyEntity1> MyEntityRepository1, IRepository<MyEntity2> MyEntityRepository2, IRepository<MyEntity3> MyEntityRepository3, IRepository<MyEntity4> MyEntityRepository4, IRepository<MyEntity5> MyEntityRepository5, IRepository<MyEntity6> MyEntityRepository6, ) {
            this.MyEntityRepo1 = MyEntityRepository1;
            this.MyEntityRepo2 = MyEntityRepository2;
            this.MyEntityRepo3 = MyEntityRepository3;
            this.MyEntityRepo4 = MyEntityRepository4;
            this.MyEntityRepo5 = MyEntityRepository5;
            this.MyEntityRepo6 = MyEntityRepository6;
        }

        public ProcessResponse Process(string UniqueKey) {
            /* Do Work */
        }
公共类DefaultTemplateManager:IDefaultTemplateManager{
受保护的IRepository MyEntityRepo1{get;set;}
受保护的IRepository MyEntityRepo2{get;set;}
受保护的IRepository MyEntityRepo3{get;set;}
受保护的IRepository MyEntityRepo4{get;set;}
受保护的IRepository MyEntityRepo5{get;set;}
受保护的IRepository MyEntityRepo6{get;set;}
public DefaultTemplateManager(IRepository MyentityRepository 1、IRepository MyentityRepository 2、IRepository MyentityRepository 3、IRepository MyentityRepository 4、IRepository MyentityRepository 5、IRepository MyentityRepository 6、){
this.MyEntityRepository1=MyEntityRepository1;
this.MyEntityRepo2=MyEntityRepository2;
this.MyEntityRepo3=MyEntityRepository3;
this.MyEntityRepo4=MyEntityRepository4;
this.MyEntityRepo5=MyEntityRepository5;
this.MyEntityRepository6=MyEntityRepository6;
}
公共进程响应进程(字符串唯一键){
/*工作*/
}

难道你不能用ninject注册其他类,然后将repostitories直接注入到这些类中吗?如果我没记错,没有使用DependencyResolver,你就不能这样做,因为“海龟一直在往下爬”问题。因此,如果DI类被注入到控制器的构造函数中,那么我需要将已解析的类传递到任何想要使用它的类中。在某些情况下,我正是这样做的,但这会导致一些更复杂进程的大量参数。依赖项