WebAPI2使用Autofac實現IOC屬性注入完美解決方案


一、前言

只要你是.NETer你一定IOC,IOC里面你也會一定知道Autofac,上次說了在MVC5實現屬性注入,今天實現在WebApi2實現屬性注入,順便說一下autofac的程序集的注入方式,都會在后面的代碼里面有提現

在WebAPI2使用Autofac注入的時候大多數人會出現如下問題:

未能加載文件或程序集“System.Web.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一個依賴項。找到的程序集清單定義與程序集引用不匹配。 (異常來自 HRESULT:0x80131040)

截圖如下:

這個是Autofac強依賴造成的,比較坑的。解決辦法如下。

Nuget添加Microsoft.AspNet.WebApi

或通過NuGet 程序包管理器控制台添加:

Install-Package Microsoft.AspNet.WebApi

Update-Package Microsoft.AspNet.WebApi -reinstall(存在)

原因:我們新建的是一個空的MVC項目,缺少引用

 

先上個結構圖,結構圖只是為了說明webAPI如何簡單使用Autofac實現屬性注入。

屬性注入存在安全隱患,官方建議使用構造函數注入。

下面說下具體實現:

二、代碼實現

1、新建一個WebAPI.Entity類庫,新建一個Person.cs類

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

2、新建WebAPI.IRepository類庫,新建一個IPersonRepository類

    public interface IPersonRepository
    {
        List<Person> GetAll();
        Person Get(int id);
        Person Add(Person item);
        bool Update(Person item);
        bool Delete(int id);
    }

3、新建WebAPI.Repository類庫,新建一個PersonRepository類實現IPersonRepository接口

public class PersonRepository : IPersonRepository
    {
        List<Person> person = new List<Person>();

        public PersonRepository()
        {
            Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中國上海" });
            Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中國上海" });
            Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中國上海" });
        }
        public List<Person> GetAll()
        {
            return person;
        }
        public Person Get(int id)
        {
            return person.Find(p => p.Id == id);
        }
        public Person Add(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            person.Add(item);
            return item;
        }
        public bool Update(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = person.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            person.RemoveAt(index);
            person.Add(item);
            return true;
        }
        public bool Delete(int id)
        {
            person.RemoveAll(p => p.Id == id);
            return true;
        }
    }

4、新建WebAPI.IServices類庫,新建IPersonServices接口

    public interface IPersonServices
    {
        List<Person> GetAll();
    }

5、IPersonServices接口在WebAPI.Services類庫里面PersonServices實現

    public class PersonServices : IPersonServices
    {
        //程序集屬性注入
        public IPersonRepository iPerson;

        public List<Person> GetAll()
        {
            return iPerson.GetAll();
        }
    }

6、新建一個WebAPI項目WebAPI,新建AutoFacBootStrapper類,nuget安裝autofac

public class AutoFacBootStrapper
    {
        public static void CoreAutoFacInit()
        {
            var builder = new ContainerBuilder();
            HttpConfiguration config = GlobalConfiguration.Configuration;

            SetupResolveRules(builder);

            ////注冊所有的Controllers
            //builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            //注冊所有的ApiControllers
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            var container = builder.Build();
            //注冊api容器需要使用HttpConfiguration對象
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

        private static void SetupResolveRules(ContainerBuilder builder)
        {
            //WebAPI只用引用services和repository的接口,不用引用實現的dll。
            //如需加載實現的程序集,將dll拷貝到bin目錄下即可,不用引用dll
            var iServices = Assembly.Load("WebAPI.IServices");
            var services = Assembly.Load("WebAPI.Services");
            var iRepository = Assembly.Load("WebAPI.IRepository");
            var repository = Assembly.Load("WebAPI.Repository");

            //根據名稱約定(服務層的接口和實現均以Services結尾),實現服務接口和服務實現的依賴
            builder.RegisterAssemblyTypes(iServices, services)
              .Where(t => t.Name.EndsWith("Services"))
              .AsImplementedInterfaces();

            //根據名稱約定(數據訪問層的接口和實現均以Repository結尾),實現數據訪問接口和數據訪問實現的依賴
            builder.RegisterAssemblyTypes(iRepository, repository)
              .Where(t => t.Name.EndsWith("Repository"))
              .AsImplementedInterfaces();
        }
    }

7、程序啟動注入

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //程序啟動注入
            AutoFacBootStrapper.CoreAutoFacInit();
        }

8.接口調用數據

        public IPersonServices IServices { get; set; }
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            var list = IServices.GetAll();
            return new string[] { "value1", "value2" };
        }

9.運行訪問api/values/,打個斷點看下搞定

三、總結

autofac確實用起來很方便,上面只是簡單的實現,如果想深入學習可以下載我上一個文章提供的兩個開源的項目可以學習下,也可以到autofac官網去了解下。

最近在看相關文章,很多都太專業化了沒怎么看懂,這是自己現在對IoC的一些理解,記錄下來,要不然時間一久,也就忘了。

自己對IoC模式理解還很淺,希望得到各位的指點。

代碼下載:

https://yunpan.cn/c6QCURhYmGcP9 (提取碼:e97a)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM