【问题标题】:Dependency injection code level依赖注入代码级别
【发布时间】:2017-05-01 15:16:05
【问题描述】:

关于依赖注入,我在概念方面和 c# 编码级别遇到问题。到目前为止,我知道我们可以使用 unity 或 autofac 来解决依赖关系。但是我的代码有问题,不管这是否正确。

项目有 4 层。

  1. 网络项目

  2. 服务水平

  3. 存储库级别

  4. 实体

这是我的 MVC 控制器级代码(在 Web 项目中)

public class EmployeeController : Controller
{
    private readonly IEmployeeService _employeeService;

    public EmployeeController() : this(new EmployeeService())
    {


    }

    public EmployeeController(IEmployeeService employeeService)
    {
        _employeeService = employeeService;
    }

    public ActionResult EmployeeList()
    {
        try
        {
            EmployeeVM empVM;
            List<EmployeeVM> lstEmpVM = new List<ViewModel.EmployeeVM>();
            var empList = _employeeService.GetAllEmployeeList();

            //below foreach use to map domain object to viewmodel object.

            foreach (var item in empList)
            {
                empVM = new EmployeeVM();
                empVM.EmployeeId = item.EmployeeId;
                empVM.Department = item.Department;
                empVM.FirstName = item.FirstName;
                empVM.LastName = item.LastName;
                empVM.Permenent = item.Permanent;
                lstEmpVM.Add(empVM);
            }

            return View(lstEmpVM);
        }
        catch (Exception ex)
        {
            throw;
        }

    }
}

这是我的EmployeeService服务级别代码(在服务级别)

public class EmployeeService : IEmployeeService
{
    private readonly IEmployeeRepository _empRepository;

    public EmployeeService() : this(new EmployeeRepository())
    {

    }


    public EmployeeService(IEmployeeRepository empRepository)
    {
        _empRepository = empRepository;
    }

    public IEnumerable<Employee> GetAllEmployeeList()
    {
        try
        {
            var ObjEmpList = _empRepository.GetEmployees();
            return ObjEmpList;

        }
        catch (Exception ex)
        {

            throw;
        }

    }

    //Some logical code going here

}

这是EmployeeService的接口

public interface IEmployeeService
{
    IEnumerable<Employee> GetAllEmployeeList();

}

有一个repository,和上面的编码一样连接数据层。

请告诉我我上面的代码可以使用依赖注入,还是我应该更改任何代码?其实我没有任何正确的想法,这些模块是否正确解耦。

【问题讨论】:

  • 只需从 EmployeeControllerEmployeeService 类中删除默认的无参数构造函数,您的代码就适合 DI。使用这些默认构造函数,您当前可以在不同层和依赖项的特定实现之间进行耦合。将特定实现注入服务应该是 DI 框架的责任。
  • 如果您在项目中实际使用 Unity 或 Autofac,那么您不需要上述任何类的默认构造函数。鉴于依赖项配置正确,它们将在运行时解决,而无需您担心。
  • 如果我不打算使用 unity 或 autofac,我真的不能用 DI 做我的项目吗?
  • @weeraa - 如果您不想使用容器,可以使用pure DI。该容器是完全可选的 - 但您仍然需要绑定到您使用正确扩展点的任何框架,以便从 composition root 解决依赖关系。在 MVC 中,可以是 IControllerFactoryIDependencyResolver

标签: c# asp.net-mvc dependency-injection


【解决方案1】:

你不需要那些默认构造函数..
您需要在依赖容器 autofac... 中注册类/接口的代码中某处可能位于 global.ascx 中。你能提供那个代码吗...?

您也可以通过扫描您的程序集来实现这一点,如此链接中所示 Autofac Scanning Assemblies for certain class type

【讨论】:

  • 其实我还没有实现 actofac 解析器。我只想检查我的代码是否可以使用 DI?
【解决方案2】:

正如达林在他的评论中提到的那样。根据您提供的代码,只需删除您提供的无参数构造函数。所以删除所有看起来像这样的构造函数

        public EmployeeController() : this(new EmployeeService())
        {
        }

这被认为是Poor man's DI

要使用容器实现您想要的,您需要 1. 将控制器工厂更换为可感知容器的控制器。 2. 向容器注册所有接口/实现类

所以对于1.你需要这样做(所有的例子都使用Windsor,但是概念是一样的)

public class WindsorControllerFactory : DefaultControllerFactory
{
    // Fields
    private readonly IKernel _kernel;

    // Methods
    public WindsorControllerFactory(IKernel kernel)
    {
        if (kernel == null)
            throw new ArgumentNullException("kernel");

        _kernel = kernel;
    }

    protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType == null)
            throw new HttpException(0x194,
                string.Format(
                    "The controller for path '{0}' could not be found or it does not implement IController.",
                    context.HttpContext.Request.Path));

        return (IController) _kernel.Resolve(controllerType);
    }
}

在 Global.asax 中,创建您的容器并注册依赖项

        Container = new WindsorContainer().Install(FromAssembly.This());

不是安装(..)。这是查找所有“安装程序”的 Windsor 功能

public class ControllersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .BasedOn<IController>()
            .LifestyleTransient());
    }
}

这个“安装程序”概念是温莎的东西。注意里面的注册码。您将拥有看起来像这样的代码,您将每个接口注册到相应的服务。

并更换控制器工厂。

        ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container.Kernel));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2019-11-27
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多