博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web API 之SelfHost与OwinSelfHots加载外部程序
阅读量:5815 次
发布时间:2019-06-18

本文共 7681 字,大约阅读时间需要 25 分钟。

   下面就一些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
GetAssemblies();}   
DefaultAssembliesResolver
     默认的AssembliesResolver为DefaultAssembliesResolver,根据以下代码片段得知,默认返回的是当前应用程序域的程序集
  
public class DefaultAssembliesResolver : IAssembliesResolver{    public virtual ICollection
GetAssemblies() { return AppDomain.CurrentDomain.GetAssemblies().ToList
(); }}  
 
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
(url: baseAddress); Console.WriteLine("程序已启动,按任意键退出"); Console.ReadLine(); }

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

       1.2通过自定义AssembliesResolber来进行注册      
         
public class UserResolver: DefaultAssembliesResolver    {        public override ICollection
GetAssemblies() { ICollection
baseAssemblies = base.GetAssemblies(); List
assemblies = new List
(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
GetAssemblies() { ICollection
baseAssemblies = base.GetAssemblies(); List
assemblies = new List
(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节点
       
       添加AssemblyResolver类,并注册
     
public class WebApiResolver: DefaultAssembliesResolver    {        public override ICollection
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如下
     

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

转载于:https://www.cnblogs.com/tiaoshuidenong/p/6768316.html

你可能感兴趣的文章
SGU 229 Divide and conquer(模拟)
查看>>
谈谈代码的阅读
查看>>
用电影凭吊青春
查看>>
Maven —— 如何设置HTTP代理
查看>>
contiki ipv6测试问题
查看>>
工控随笔_02_西门子_WinCC的IO域利用C脚本返回值
查看>>
Nginx负载均衡
查看>>
关于在Asp.net下使用Oracle.DataAccess.dll(Oracle10g)执行参数化Update无效的解决方案之一...
查看>>
Apache Rewrite 命令
查看>>
jquery.get中文参数问题——js符串编码
查看>>
js分页例子
查看>>
Linux汇编---函数调用过程
查看>>
SuperMap iServer Java 2008硬件许可配置历险记(转)
查看>>
滚动标记当前菜单状态
查看>>
【APUE笔记一】进程相关ID
查看>>
使用python抓取58手机维修信息
查看>>
SQL Server 2008 常见异常收集(持续更新)
查看>>
AnnotationSessionFactoryBean用法介绍
查看>>
Array转为Json需要导入的包
查看>>
cmake编译Debug和Release
查看>>