前言

自從幾年前拋棄wcf,使用web api 來做服務器端開發(fā)之后,就不再迷惑了。但是因為本來從事傳統(tǒng)行業(yè)管理軟件開發(fā),一般都以分布式應用開發(fā)為主。純BS還是比較少,于是比較喜歡用windows service來宿主web api。發(fā)現這種場景網上文章還是比較少。這次就結合最近的技術嘗試(DI、IOC),整體介紹一下這方面的實踐。

名詞解釋

依賴注入

依賴倒置原則 A.高層次的模塊不應該依賴于低層次的模塊,他們都應該依賴于抽象。B.抽象不應該依賴于具體實現,具體實現應該依賴于抽象。 DI—Dependency Injection,即“依賴注入”組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態(tài)的將某個依賴關系注入到組件之中。依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,而是為了提升組件重用的頻率,并為系統(tǒng)搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業(yè)務邏輯,而不需要關心具體的資源來自何處,由誰實現。

  理解DI的關鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,那我們來深入分析一下:

  ●誰依賴于誰:當然是應用程序依賴于IoC容器;

  ●為什么需要依賴:應用程序需要IoC容器來提供對象需要的外部資源

  ●誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象;

  ●注入了什么:就是注入某個對象所需要的外部資源(包括對象、資源、常量數據)。

 控制反轉:控制反轉即IoC (Inversion of Control),它把傳統(tǒng)上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。 我綁架了一個人質,對圍觀的警察說:我要一輛紅色法拉利,才能釋放人質。但其實我只是希望要一輛車而已。要法拉利很容易被拒絕,還可能引起很嚴重的后果。如果我說要一輛車,那么警察估計更容易給我一輛普通車... 在軟件開發(fā)里面的就是盡量使用接口對象,而不使用具體明確的對象(依賴外部注入的接口對象),以此達到解除耦合的目的。哎我自己也理解得不深刻,其實我要說的是:owin+web api+autofac.上面的解釋是我抄的,理解不了就算了吧。后面這些總該知道什么東西吧。 

開發(fā)工具和包

IDE: VS2015

Package:

1234567891011121314151617181920212223<?xml version="1.0" encoding="utf-8"?><packages>  <package id="Autofac" version="4.4.0" targetFramework="net45" />  <package id="Autofac.Owin" version="4.0.0" targetFramework="net45" />  <package id="Autofac.WebApi2" version="4.0.1" targetFramework="net45" />  <package id="Autofac.WebApi2.Owin" version="4.0.0" targetFramework="net45" />  <package id="EntityFramework" version="6.1.3" targetFramework="net45" />  <package id="EntityFramework.zh-Hans" version="6.1.3" targetFramework="net45" />  <package id="LitJson" version="0.7.0" targetFramework="net45" />  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net45" />  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.3" targetFramework="net45" />  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />  <package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net45" />  <package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net45" />  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />  <package id="Owin" version="1.0" targetFramework="net45" />  <package id="System.Data.SQLite" version="1.0.104.0" targetFramework="net45" />  <package id="System.Data.SQLite.Core" version="1.0.104.0" targetFramework="net45" />  <package id="System.Data.SQLite.EF6" version="1.0.104.0" targetFramework="net45" />  <package id="System.Data.SQLite.Linq" version="1.0.104.0" targetFramework="net45" /></packages>

targetFramework:net45,注意一下運行時是4.5以上,也是說服務程序必須在win7 sp1以上的操作系統(tǒng)才能運行。

 

編碼細節(jié)和要點

1、windows服務宿主web api

1234567891011121314151617181920212223242526272829303132333435363738//protected override        public new void OnStart(string[] args)        {            try            {                string middleware_url = string.Join(""new string[] { "http://", MiddlewareIP, ":", MiddlewarePort });                hostObject = WebApp.Start<Startup>(middleware_url);                if (hostObject != null)                    Com.DataCool.DotNetExpand.LogHelper.Info("中間件宿主WebApi成功,URL:" + middleware_url);                else                    Com.DataCool.DotNetExpand.LogHelper.Error("中間件宿主WebApi錯誤!");                string result = HttpAPIRequest();                if (!string.IsNullOrEmpty(result))                    Com.DataCool.DotNetExpand.LogHelper.Info(result);            }            catch (Exception ex)            {                Com.DataCool.DotNetExpand.LogHelper.Error(ex);            }            IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0);            EndPoint epSender = (EndPoint)ipeSender;            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            // 首次探測時間5 秒, 間隔偵測時間2 秒            byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0xd0, 0x07, 0, 0 };            serverSocket.IOControl(IOControlCode.KeepAliveValues, inValue, null);            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(MiddlewareIP), 5880);            try            {                serverSocket.Bind(ipEndPoint);                serverSocket.Listen(1024);                socketThread = new Thread(ListenClientConnect);                socketThread.Start();            }            catch (Exception ex)            {                Com.DataCool.DotNetExpand.LogHelper.Error("服務啟動失敗,原因:" + ex.Message);            }        }

  其實就一句話:hostObject = WebApp.Start<Startup>(middleware_url);這個Startup是用來配置web api的路由規(guī)則和實現autofac初始流程的。

123456789101112131415161718192021222324252627282930313233343536public class Startup   {       public void Configuration(IAppBuilder appBuilder)       {           HttpConfiguration config = new HttpConfiguration();           //自定義路由           config.Routes.MapHttpRoute(             name: "CustomApi",             routeTemplate: "api/{controller}/{action}/{id}",             defaults: new { id = RouteParameter.Optional }           );           //規(guī)范api格式僅僅支持XML           var xmlFormatter = new XmlMediaTypeFormatter();           config.Services.Replace(typeof(IContentNegotiator), new XmlContentNegotiator(xmlFormatter));            var builder = new ContainerBuilder();           //注冊本程序集內的ApiControllers           builder.RegisterApiControllers(Assembly.GetExecutingAssembly());           //內置日志服務注冊           builder.Register(c => new ServiceLog()).As<IServiceLog>().InstancePerRequest();            var iServices = Assembly.Load("Van.Interface");           var services = Assembly.Load("Van.Service");           //根據名稱約定(服務層的接口和實現均以Service結尾),實現服務接口和服務實現的依賴           builder.RegisterAssemblyTypes(iServices, services)             .Where(t => t.Name.EndsWith("Service"))             .AsImplementedInterfaces();            var container = builder.Build();           config.DependencyResolver = new AutofacWebApiDependencyResolver(container);            appBuilder.UseAutofacMiddleware(container);            appBuilder.UseAutofacWebApi(config);           appBuilder.UseWebApi(config);       }   }

  

 

請看一下注釋,友情提示本篇文章的“高潮“部分就在這里,任何解釋都是蒼白的。哈哈哈...

2、使用注入的接口對象

http://www.cnblogs.com/datacool/p/datacool_2017_webapi_owin_autofac.html