下面就一些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 = ":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(":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进行加载