65.9K
CodeProject 正在变化。 阅读更多。
Home

使用特性和反射在 ASP.NET Web API 中进行依赖注入

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.05/5 (8投票s)

2017 年 8 月 15 日

CPOL

2分钟阅读

viewsIcon

24941

通过特性和反射解析依赖

引言

在本文中,我们将了解如何创建一个依赖注入特性并在整个应用程序中使用它,从而消除冗余代码。

我将使用 AutoFac WebApi 容器作为我的依赖注入解析器。

问题

当我们开始在项目中为依赖项使用任何容器时,我们会编写大量的冗余代码,如下所示。

            builder.RegisterType<<wbr />EmployeeManager>().As<<wbr />IEmployeeManager>();
            builder.RegisterType<<wbr />CustomerManager>().As<<wbr />ICustomerManager>();
            builder.RegisterType<<wbr />EmployeeRepository>().As<<wbr />IEmployeeRepository>();
            builder.RegisterType<<wbr />CustomerRepository>().As<<wbr />ICustomerRepository>();

                                               ...

                                               ...

            builder.RegisterType<<wbr />CustomerManager>().As<<wbr />ICustomerManager>();
            builder.RegisterType<<wbr />EmployeeRepository>().As<<wbr />IEmployeeRepository>();
            builder.RegisterType<<wbr />CustomerRepository>().As<<wbr />ICustomerRepository>();

随着项目规模的增长,依赖构建器的行数也会增加。

这其中存在多个问题。

1. 每次想要添加依赖项时,都需要进入依赖类并添加相关的依赖项。
2. 在合并代码时,开发人员可能会覆盖一些依赖项。
3. 该类会不断增长,并且在某个时候你会觉得它难以维护。
4. 这将违反 SOLID 原则的开放/封闭原则

解决方案

现在我们将看到如何通过特性和反射解决这些冗余代码。

步骤 1

我们将在此项目中创建一个公共库,并创建一个继承 System 命名空间下 Attribute 类的 InjectableAttribute 类。

     using System; 
     namespace AutoFacCommon 
     { 
        public class InjectableAttribute : Attribute
        { 
   
        } 
     }

我使用了“InjectableAttribute”作为名称,因为 Angular2 具有名为 Injectable 的依赖注入。希望同步客户端和服务器。

第二步

现在,由于我们已经创建了 Injectable 特性,我们需要用这个特性装饰类。

    [Injectable]
    public class EmployeeManager : IEmployeeManager
    {
        private readonly IEmployeeRepository _employeeRepository;

        public EmployeeManager(<wbr />IEmployeeRepository employeeRepository)
        {
            _employeeRepository = employeeRepository;
        }

        public IList<Employee> GetAllEmployess()
        {
            var employeeData = _employeeRepository.<wbr />GetAllEmployees();
            var employeeList = new List<Employee>();
            foreach (var employee in employeeData)
            {
                var employ = new Employee();
                employ.EmployeeDesignation = employee.EmployeeDesignation;
                employ.EmployeeId = employee.EmployeeId;
                employ.EmployeeName = employee.EmployeeName;
                employeeList.Add(employ);
            }
            return employeeList;
        }
    }

注意:当您看到用 [Injectable] 特性装饰的类时,这意味着该类已准备好被注入。无论何时需要该类,都可以注入。

步骤 3

现在让我们在 WebApi 控制器中注入这个类,如下所示。

    public class EmployeeController : ApiController
    {
        private readonly IEmployeeManager _employeeManager;

        public EmployeeController(<wbr />IEmployeeManager employeeManager)
        {
            _employeeManager = employeeManager;
        }

        [AllowAnonymous]
        [ResponseType(typeof(Employee)<wbr />)]
        public IHttpActionResult GetEmployees()
        {
            var employeeData = _employeeManager.<wbr />GetAllEmployess();
            return Ok(employeeData);
        }
    }

当您从 swagger 或 postman 运行上述代码时,它会起作用吗? 不,我们是否告诉 CLR 解析依赖项? 到目前为止,我们还没有做任何事情。

现在我们来做吧。

步骤 4

您需要从 NuGet 包管理器下载 Autofac.WebApi2 和 AutoFac。

我们将构建一个名为 Static AutoFacDependencyBuilder 的静态类,如下所示。

    public static class AutofacDependecyBuilder
    {

        public static void DependencyBuilder()
        {
            // Create the builder with which components/services are registered.
            var builder = new ContainerBuilder();

            // Register your Web API controllers.
            builder.<wbr />RegisterApiControllers(<wbr />Assembly.GetExecutingAssembly(<wbr />));

            builder.RegisterAssemblyTypes(<wbr />AppDomain.CurrentDomain.<wbr />GetAssemblies())
                                      .Where(t => t.GetCustomAttribute<<wbr />InjectableAttribute>() != null)
                                      .AsImplementedInterfaces()
                                      .InstancePerRequest();

            builder.<wbr />RegisterWebApiFilterProvider(<wbr />GlobalConfiguration.<wbr />Configuration);

            //Build the Container
            var container = builder.Build();

            //Create the Dependency Resolver
            var resolver = new AutofacWebApiDependencyResolve<wbr />r(container);

            //Configuring WebApi with Dependency Resolver
            GlobalConfiguration.<wbr />Configuration.<wbr />DependencyResolver = resolver;

        }

    }

上述加粗的代码是会将所有部分组合在一起的关键。

这段代码将在项目首次加载时加载所有程序集。它将使用反射获取所有自定义特性并创建按请求实例化的对象。 在我们的例子中,它是 Injectable 自定义特性。

步骤 5

好的,经过所有的努力工作,我们需要在 Global.asax 或 App.Start 文件中初始化 AutoFac 依赖构建器类,如下所示。

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(<wbr />WebApiConfig.Register);
            AutofacDependecyBuilder.<wbr />DependencyBuilder();
        }
    }

现在我们可以说它会完美地工作。

如果您不想经历所有的努力工作,可以访问下面的存储库链接。它应该可以帮助您入门。

© . All rights reserved.