前言

自从几年前抛弃wcf,使用web api 来做服务器端开发之后,就不再迷惑了。但是因为本来从事传统行业管理软件开发,一般都以分布式应用开发为主。纯BS还是比较少,于是比较喜欢用windows service来宿主web api。发现这种场景网上文章还是比较少。这次就结合最近的技术尝试(DI、IOC),整体介绍一下这方面的实践。

名词解释

依赖注入

依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。 DI—Dependency Injection,即“依赖注入”组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

  理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  ●谁依赖于谁:当然是应用程序依赖于IoC容器

  ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

  ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象

  ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

 控制反转:控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。 我绑架了一个人质,对围观的警察说:我要一辆红色法拉利,才能释放人质。但其实我只是希望要一辆车而已。要法拉利很容易被拒绝,还可能引起很严重的后果。如果我说要一辆车,那么警察估计更容易给我一辆普通车... 在软件开发里面的就是尽量使用接口对象,而不使用具体明确的对象(依赖外部注入的接口对象),以此达到解除耦合的目的。哎我自己也理解得不深刻,其实我要说的是:owin+web api+autofac.上面的解释是我抄的,理解不了就算了吧。后面这些总该知道什么东西吧。 

开发工具和包

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以上的操作系统才能运行。

 

编码细节和要点

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的路由规则和实现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 }           );           //规范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

延伸阅读

告别“老顽固”-Java培训,做最负责任的教育,学习改变命运,软件学习,再就业,大学生如何就业,帮大学生找到好工作,lphotoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训告别“老顽固”