下面就一些web api的一些基础内容进行阐述,然后就web api宿主承载中的实际业务问题进行解决
HttpController
     HttpController的激活是由处于消息处理管道尾端的HttpRoutingDispatcher来完成的,具体来说是HttpRoutingDispatcher利用HttpControllerDispatcher实现了针对目标HttpController的激活和执行。激活目标HttpController的前提是能够正确解析出HttpController的真实类型,而类型解析需要针对加载的程序集,所以我们需要先来了解一个用于解析程序集的对象AssembliesResolver。在ASP.NET Web API的HttpController激活系统中,AssembliesResolver为目标HttpController的类型解析提供候选的程序集。换句话说,候选HttpController类型的选择范围仅限于定义在通过AssembliesResolver提供的程序集中的所有实现了IHttpController接口的类型
AssembliesResolver
     所有的AssembliesResolver均实现了IAssembliesResolver接口。根据程序反射得到如下代码片段,根据代码片段得知,IAssembliesResolver提供的是程序集列表

public interface IAssembliesResolver
{
    ICollection<Assembly> GetAssemblies();
}
   
DefaultAssembliesResolver
     默认的AssembliesResolver为DefaultAssembliesResolver,根据以下代码片段得知,默认返回的是当前应用程序域的程序集

public class DefaultAssembliesResolver : IAssembliesResolver
{
    public virtual ICollection<Assembly> GetAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>();
    }
}  
 
ServicesContainer
      默认的AssembliesResolver就是通过ServicesContainer类型确定
      Web Api的请求相当于一个管道,类似于流水线作业,每个环节都会注册自己的实现类组件来完成自己的工作。这些组件都会实现自己特定的接口,当然在预置的组件无法满足我们的业务需求时,可以自己来实现组件代码,并进行注册,ServicesContainer其实可以简单的理解为这些组件的一个IOC容器
 
     上面所介绍的就代表着,如果采用selfHost承载web api,而且web api与宿主程序不在同一程序集中的情况,如果在用上篇的代码,将会发现报以下错误  No type was found that matches the controller named 'User'.
    上面所说的情况,分两种,第一种,单个api程序集,多个api程序集
    1.如果api程序集全部写在一个单独的程序集中的情况
    1.1 直接通过Assembly加载外部程序集

        static void Main(string[] args)
        {
            // 如果 API 处于外部程序集,可通过以下代码加载 CM.API为其他程序集
            //Assembly.Load("CM.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");    //加载外部程序集
            string baseAddress = "http://localhost:9000/";
            // 启动 OWIN host
            WebApp.Start<Startup>(url: baseAddress);
            Console.WriteLine("程序已启动,按任意键退出");
            Console.ReadLine();
        }

宿主项目还是需要引用CM.API程序集

       1.2通过自定义AssembliesResolber来进行注册      

    public class UserResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
            var assembly = AppDomain.CurrentDomain.BaseDirectory;
            string path = assembly + "\\" + "CM.API.dll";
            var controllersAssembly = Assembly.LoadFrom(path);
            baseAssemblies.Add(controllersAssembly);
            return assemblies;
        }
    }
         然后宿主启动时进行注册        

        static void Main(string[] args)
        {
            var config = new HttpSelfHostConfiguration("http://localhost:8083");
            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            //注册UserResolver,加载程序集
            config.Services.Replace(typeof(IAssembliesResolver), new UserResolver());
            using (var server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
      2.当然在业务开发中如果API被分散开发到多个程序集中,这种情况当然根据项目框架区分,各有利弊
      2.1 通过上述的UserServoler进行加载      
    public class UserResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
            var assembly = AppDomain.CurrentDomain.BaseDirectory;
            string path = assembly + "\\" + "CM.API.dll";
            var controllersAssembly = Assembly.LoadFrom(path);
            baseAssemblies.Add(controllersAssembly);
            //加载多个程序集   不建议写死
            string path2 = assembly + "\\" + "CM.API2.dll";
            var controllersAssembly2 = Assembly.LoadFrom(path2);
            baseAssemblies.Add(controllersAssembly2);
            return assemblies;
        }
    }
       上述代码只是展示加载的一种方式,只是得到程序集的方式需要去进行配置编码,不建议直接写死在代码里
       2.2 通过自定配置类,进行配置文件读取加载
            添加自定义配置类        
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Reflection;

namespace CM.SelfHost
{
    public class AssembliesLoad : ConfigurationSection
    {
        [ConfigurationProperty("", IsDefaultCollection = true)]
        public AssemblyElementCollection AssemblyNames
        {
            get { return (AssemblyElementCollection)this[""]; }
        }

        public static AssembliesLoad GetSection()
        {
            return ConfigurationManager.GetSection("AssembliesLoad") as AssembliesLoad;
        }
    }
    public class AssemblyElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new AssemblyElement();
        }
        protected override object GetElementKey(ConfigurationElement element)
        {
            AssemblyElement serviceTypeElement = (AssemblyElement)element;
            return serviceTypeElement.AssemblyName;
        }
    }

    public class AssemblyElement : ConfigurationElement
    {
        [ConfigurationProperty("assemblyName", IsRequired = true)]
        public string AssemblyName
        {
            get { return (string)this["assemblyName"]; }
            set { this["assemblyName"] = value; }
        }
    }
} 
        添加配置文件,如下,加入ConfigSections节点以及AssembliesLoad节点

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <configSections>
    <section name="AssembliesLoad" type="CM.SelfHost.AssembliesLoad,CM.SelfHost"/>
  </configSections>
  <AssembliesLoad>
    <add assemblyName="CM.API.dll" />
  </AssembliesLoad>
</configuration>
       添加AssemblyResolver类,并注册

    public class WebApiResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            AssembliesLoad settings = AssembliesLoad.GetSection();
            if (null != settings)
            {
                foreach (AssemblyElement element in settings.AssemblyNames)
                {
                    AssemblyName assemblyName = AssemblyName.GetAssemblyName(element.AssemblyName);
                    if (!AppDomain.CurrentDomain.GetAssemblies().Any(assembly =>
                        AssemblyName.ReferenceMatchesDefinition(assembly.GetName(), assemblyName)))
                    {
                        AppDomain.CurrentDomain.Load(assemblyName);
                    }
                }
            }
            return base.GetAssemblies();
        }
    }
      注册Resolver        
        static void Main(string[] args)
        {
            //Assembly.Load("CM.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");    //加载外部程序集
            var config = new HttpSelfHostConfiguration("http://localhost:8083");
            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            config.Services.Replace(typeof(IAssembliesResolver), new UserResolver());
            using (var server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
      运行会报错 其他信息: 配置系统未能初始化
      查阅一些说明之后发现,如果存在自定义配置ConfigSections节点,那么必须在第一个节点,修改app.confg如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="AssembliesLoad" type="CM.SelfHost.AssembliesLoad,CM.SelfHost"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <AssembliesLoad>
    <add assemblyName="CM.API.dll" />
  </AssembliesLoad>
</configuration>

至此,web api的承载方式就已经阐述完毕,说一下个人倾向,通过两篇文章对承载的了解,我喜欢使用OwinselfHost承载,并采用自定义配置文件的方式加载外部api程序集,Owin有跨平台功能,但没有去进行验证,大家有兴趣可以去验证下

Web API 之SelfHost与OwinSelfHots加载外部程序的更多相关文章

  1. Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问题

    Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问 ...

  2. web.xml中配置启动时加载的servlet,load-on-starup

    web.xml中配置启动时加载的servlet,load-on-starup 使用servlet来初始化配置文件数据: 在servlet的配置当中,<load-on-startup>1&l ...

  3. java web.xml listener servlet 和filter加载顺序

    在该项目中总会遇到一些关于加载的优先问题.最近遇到了同样的类别似的,所以,如果你发现信息汇总下,以下是转载其他一些人,毕竟,人们写的不错.它不重复创建的轮.只是略作修改自己的观点. 首先能够肯定的是, ...

  4. AMD和RequireJS初识----优化Web应用前端(按需动态加载JS)

    RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的RequireJS压缩后只有14K,堪称非常轻量.它还同时可以和其他的框架协同工作,使用Re ...

  5. Android浏览本地 API文档 + 解决页面加载慢的问题

    火狐浏览器安装离线浏览插件: 用浏览器打开index.html文件,你会发现加载的很慢,原因你懂的,为此,我们可以通过离线的方式 查看本地API文档,用火狐浏览器  +   Work Offline插 ...

  6. 移动端web页面列表类上拉加载,查看详情,iframe嵌套第三方页面遇到的问题以及解决办法

    1.移动端上拉加载 网上有很多成熟的插件,比如iscroll.在这里介绍一下用jquery和js写的上拉加载方法.使用原生的去写上拉加载更多需要三个高度去做对比,以新闻类列表举例,首先需要整个dom的 ...

  7. Java之——Web项目中DLL文件动态加载方法

    本文转自:https://blog.csdn.net/l1028386804/article/details/53903557 在Java Web项目中,我们经常会用到通过JNI调用dll动态库文件来 ...

  8. arcgis api for javascript本地部署加载地图

    最近开始学习arcgis api for javascript,发现一头雾水,决定记录下自己的学习过程. 一.下载arcgis api for js 4.2的library和jdk,具体安装包可以去官 ...

  9. web.xml中监听器如何顺序加载

    最近用到在Tomcat服务器启动时自动加载数据到缓存,这就需要创建一个自定义的缓存监听器并实现ServletContextListener接口, 并且在此自定义监听器中需要用到Spring的依赖注入功 ...

随机推荐

  1. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

  2. WeMall微信商城源码插件代金券部分代码

    WeMall微信商城源码插件Coupon代金券代码是用于商业推广的比较有效的方式,分享了部分比较重要的代码,供技术员学习参考 AdminController.class.php <?php na ...

  3. Go语言并发机制初探

    Go 语言相比Java等一个很大的优势就是可以方便地编写并发程序.Go 语言内置了 goroutine 机制,使用goroutine可以快速地开发并发程序, 更好的利用多核处理器资源.这篇文章学习 g ...

  4. (20)IO流之SequenceInputStream 序列流

    序列流,对多个流进行合并. SequenceInputStream 表示其他输入流的逻辑串联.它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直 ...

  5. windows phone 8.1开发:磁铁|Tile更新

    原文出自:http://www.bcmeng.com/tile/ 上一篇给大家分享了toast通知操作的方法,这一篇文章我们就来看windows phone 8.1开发中的磁铁更新.磁铁是window ...

  6. Frame框架

    框架 frameset    框架集    如果使用框架集,当前页面不能有body    cols="300,*" :左右拆分,左边宽300,右边宽剩余    rows=" ...

  7. linux最小安装

    (1)系统安装类型选择及自定义额外包组 进入如图2-28所示界面.上半部分是系统定制的不同的系统安装类型选择项,默认是“Desktop”,这里我们选择“Minimal”,即最小化安装,下半部分是在上面 ...

  8. STM32GPIO口8种模式细致分析(类比51单片机)

    关于STM32GPIO口的8种工作模式,我们先引出一些问题? STM32GPIO口如果既要输入又要输出怎么办? 1.浮空输入模式 上图红色的表示便是浮空输入的过程,外部输入时0读出的就是0,外部输入时 ...

  9. 微信小程序评分功能

    很多做过电商项目的朋友会经常用到评分的功能,我这里正好写了一个例子,发出来分享一下: 我写的是5分满分制的,首先,准备3个图片, ,像这样的,分别代表分数为0,0.5,1 时的状态, 效果图:(以3. ...

  10. 老李推荐:第14章9节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-遍历控件树查找控件

    老李推荐:第14章9节<MonkeyRunner源码剖析> HierarchyViewer实现原理-遍历控件树查找控件   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员 ...