下面就一些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. 3407: [Usaco2009 Oct]Bessie's Weight Problem 贝茜的体重问题

    3407: [Usaco2009 Oct]Bessie's Weight Problem 贝茜的体重问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit:  ...

  2. 通讯录--(iOS9独有的方法)

    导入库文件   #import <ContactsUI/ContactsUI.h> #pragma mark iOS9 新出的点击通讯录的获取信息的办法 #pragma mark - 先弹 ...

  3. iOS网络编程笔记——XML文档解析

    今天利用多余时间研究了一下XML文档解析,虽然现在移动端使用的数据格式基本为JSON格式,但是XML格式毕竟多年来一直在各种计算机语言之间使用,是一种老牌的经典的灵活的数据交换格式.所以我认为还是很有 ...

  4. yii2.0使用之缓存

    1.片段缓存(针对于视图中的某部分进行缓存): <?php 设置有效时间 $time=15; 缓存依赖,存入文件.当文件内容发生改变是才会刷新新内容 $dependecy=[ 'class'=& ...

  5. Spring定时任务解决博客缓存数据更新问题

    最近在做博客系统的时候,由于很多页面都有右边侧边栏,内容包括博客分类信息,归档日志,热门文章,标签列表等,为了不想每次访问页面都去查询数据库,因为本身这些东西相对来说是比较固定的,但是也有可能在网站后 ...

  6. MCMC(四)Gibbs采样

    MCMC(一)蒙特卡罗方法 MCMC(二)马尔科夫链 MCMC(三)MCMC采样和M-H采样 MCMC(四)Gibbs采样 在MCMC(三)MCMC采样和M-H采样中,我们讲到了M-H采样已经可以很好 ...

  7. Google永远不可能回到国内,只能是回忆

    今天早上在微博上无意看 [谷歌翻译App在大陆地区恢复无障碍使用]这篇文章,不知不觉就点进去看一下,内心还是比较兴奋,为什么兴奋说不清楚.或许我们是真的喜欢Google的产品. 回想2010年Goog ...

  8. 用代码控制退出APP

    + (void)exitApplication { AppDelegate *app = [UIApplication sharedApplication].delegate; UIWindow *w ...

  9. scrollWidth,offsetWidth,clientWidth,width;scrollHeight,offsetHeight,clientHeight,height;offsetTop,scrollTop,top;offsetLeft,scrollLeft,left还有谁

    题中的那么多属性让人头都大了,他们到底是什么意思?不同浏览器的实现是一样的吗?以下所有结论来自chrome版本 53.0.2785.89 (64-bit)和firefox版本52.0.2,操作系统ub ...

  10. rxjava2学习笔记(1)

    1.什么是RxJava? 简单,清晰的多线程编程框架.可方便的写出维护性高,逻辑清晰的Java程序. 2.什么是观察者模式? 入门教程讲这种高大上抽象概念都是耍流氓! 3.开始 3.1github地址 ...