标签:from common base ansi code webapi instance start containe
ABP框架可以动态生成WebApi,开发人员无需创建APIController,直接继承IApplicationService接口,即可对外发布webApi。
创建动态Web Api 控制器
例如,在Service层有一个ITestService接口,如下:
public interface ITestService : IApplicationService
{
Listint> GetTestMethod();
string GetAll();
string GetById(int id);
}
该接口实现了“IApplicationService”接口,在该框架中,我们无需构建TestServiceApiController就可以对外发布webapi。用户可以直接通过访问“api/services/app/TestService/GetTestMethod”实现api 访问。
实现原理:
模块初始化阶段,注册动态API实现模块,在批量/单个注册方法中,执行“BatchApiControllerBuilder”的“Build”方法,遍历Application层程序集,查找所有已注册接口类型。然后根据类型信息获取服务名称,生成单个“ApiControllerBuilder”实例,依次执行“ApiControllerBuilder”中的方法。其中生成“action”是在“Builder”中实现的。
在“ApiControllerBuilder”的“Builder”方法中”,通过“Build”方法构建apiinfo信息并将“action”添加到controller中,最后在apicontroller管理类中注册controller信息。
以下对类和接口逐一分析
AbpApiController:集成了ApiController,框架中自定义的apicontroller都继承自该类;
IDynamicApiController:空接口,生成DynamicApiController标识;
DynamicApiController:动态生成ApiController类,继承自“AbpApiController”,“IDynamicApiController”;
1 public class DynamicApiController: AbpApiController, IDynamicApiController
2 {
3 public Liststring> AppliedCrossCuttingConcerns { get; }
4 public DynamicApiController()
5 {
6 AppliedCrossCuttingConcerns = new Liststring>();
7 }
8 }
DynamicApiControllerInfo:封装ApiController基本信息,其中以字典的形式存储了“DynamicApiActionInfo”;
1 public DynamicApiControllerInfo(
2 string serviceName,
3 Type serviceInterfaceType,
4 Type apiControllerType,
5 Type interceptorType,
6 IFilter[] filters = null,
7 bool? isApiExplorerEnabled = null,
8 bool isProxyScriptingEnabled = true)
9 {
10 ServiceName = serviceName;
11 ServiceInterfaceType = serviceInterfaceType;
12 ApiControllerType = apiControllerType;
13 InterceptorType = interceptorType;
14 IsApiExplorerEnabled = isApiExplorerEnabled;
15 IsProxyScriptingEnabled = isProxyScriptingEnabled;
16 Filters = filters ?? new IFilter[] { }; //Assigning or initialzing the action filters.
17 Actions = new Dictionarystring, DynamicApiActionInfo>(StringComparer.InvariantCultureIgnoreCase);
18 }
IBatchApiControllerBuilder/BatchApiControllerBuilder:批量ApiController构建器,通过“Build”方法,根据程序集,批量生成“DynamicApiControllerInfo”;
internal class BatchApiControllerBuilder : IBatchApiControllerBuilder
{
#region 声明实例
private readonly string _servicePrefix;
private readonly Assembly _assembly;
private IFilter[] _filters;
private Funcstring> _serviceNameSelector;
private Funcbool> _typePredicate;
private bool _conventionalVerbs;
private Action> _forMethodsAction;
private bool? _isApiExplorerEnabled;
private readonly IIocResolver _iocResolver;
private readonly IDynamicApiControllerBuilder _dynamicApiControllerBuilder;
private bool? _isProxyScriptingEnabled;
#endregion
#region 构造函数
public BatchApiControllerBuilder(
IIocResolver iocResolver,
IDynamicApiControllerBuilder dynamicApiControllerBuilder,
Assembly assembly,
string servicePrefix)
{
_iocResolver = iocResolver;
_dynamicApiControllerBuilder = dynamicApiControllerBuilder;
_assembly = assembly;
_servicePrefix = servicePrefix;
}
#endregion
#region 方法
public void Build()
{
var types =
from type in _assembly.GetTypes()
where (type.IsPublic || type.IsNestedPublic) &&
type.IsInterface &&
typeof(T).IsAssignableFrom(type) &&
_iocResolver.IsRegistered(type) &&
!RemoteServiceAttribute.IsExplicitlyDisabledFor(type)
select type;
if (_typePredicate != null)
{
types = types.Where(t => _typePredicate(t));
}
foreach (var type in types)
{
var serviceName=_serviceNameSelector!=null?
_serviceNameSelector(type)
: GetConventionalServiceName(type);
if (!string.IsNullOrWhiteSpace(_servicePrefix))
{
serviceName = _servicePrefix + "/" + serviceName;
}
var builder = typeof(IDynamicApiControllerBuilder)
.GetMethod("For", BindingFlags.Public | BindingFlags.Instance)
.MakeGenericMethod(type)
.Invoke(_dynamicApiControllerBuilder, new object[] { serviceName });
if (_filters != null)
{
builder.GetType()
.GetMethod("WithFilters", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] { _filters });
}
if (_isApiExplorerEnabled != null)
{
builder.GetType()
.GetMethod("WithApiExplorer", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] { _isApiExplorerEnabled });
}
if (_isProxyScriptingEnabled != null)
{
builder.GetType()
.GetMethod("WithProxyScripts", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] { _isProxyScriptingEnabled.Value });
}
if (_conventionalVerbs)
{
builder.GetType()
.GetMethod("WithConventionalVerbs", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[0]);
}
if (_forMethodsAction != null)
{
builder.GetType()
.GetMethod("ForMethods", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] { _forMethodsAction });
}
builder.GetType()
.GetMethod("Build", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[0]);
}
}
private string GetConventionalServiceName(Type type)
{
var typeName = type.Name;
typeName = typeName.RemovePostFix(ApplicationService.CommonPostfixes);
if (typeName.Length > 1 && typeName.StartsWith("I") && char.IsUpper(typeName, 1))
{
typeName = typeName.Substring(1);
}
return typeName.ToCamelCase();
}
public IBatchApiControllerBuilder ForMethods(Action action)
{
_forMethodsAction = action;
return this;
}
public IBatchApiControllerBuilder Where(Funcbool> predicate)
{
_typePredicate = predicate;
return this;
}
public IBatchApiControllerBuilder WithApiExplorer(bool isEnabled)
{
_isApiExplorerEnabled = isEnabled;
return this;
}
public IBatchApiControllerBuilder WithConventionalVerbs()
{
_conventionalVerbs = true;
return this;
}
public IBatchApiControllerBuilder WithFilters(params IFilter[] filters)
{
_filters = filters;
return this;
}
public IBatchApiControllerBuilder WithProxyScripts(bool isEnabled)
{
_isProxyScriptingEnabled = isEnabled;
return this;
}
public IBatchApiControllerBuilder WithServiceName(Funcstring> serviceNameSelector)
{
_serviceNameSelector = serviceNameSelector;
return this;
}
#endregion
}
View Code
DynamicApiControllerBuilder/IDynamicApiControllerBuilder:动态ApiController构建器。“For”方法构建了“ApiControllerBuilder”实例;“ForAll”生成了“BatchApiControllerBuilder”,用于批量生成“DynamicApiControllerInfo”实例;
IApiControllerBuilder/ApiControllerBuilder:单个ApiController构建器,每个ABPApiCon以troller中存储了“Action”的基本信息。通过“Build”方法,生成“DynamicApiControllerInfo”实例,然后遍历“Action”,添加到“IDictionary>”字典中;
1 public void Build()
2 {
3 var controllerInfo = new DynamicApiControllerInfo(
4 ServiceName,
5 ServiceInterfaceType,
6 typeof(DynamicApiController),
7 typeof(AbpDynamicApiControllerInterceptor),
8 Filters,
9 IsApiExplorerEnabled,
10 IsProxyScriptingEnabled
11 );
12 foreach (var actionBuilder in _actionBuilders.Values)
13 {
14 if (actionBuilder.DontCreate)
15 {
16 continue;
17 }
18 controllerInfo.Actions[actionBuilder.ActionName] = actionBuilder.BuildActionInfo(ConventionalVerbs);
19
20 }
21 _iocResolver.Resolve().Register(controllerInfo);
22 }
DynamicApiActionInfo:封装了“Action”名称、请求方式等基本信息;
1 ///
2 /// 封装动态生成的ApiController的Action的信息
3 ///
4 public class DynamicApiActionInfo
5 {
6 ///
7 /// action 名称
8 ///
9 public string ActionName { get; private set; }
10 ///
11 /// 方法信息
12 ///
13 public MethodInfo Method { get; private set; }
14 public HttpVerb Verb { get; private set; }
15 ///
16 /// 过滤器
17 ///
18 public IFilter[] Filters { get; set; }
19 ///
20 /// Is API Explorer enabled.
21 ///
22 public bool? IsApiExplorerEnabled { get; set; }
23 ///
24 /// 构造函数
25 ///
26 ///
27 ///
28 ///
29 ///
30 ///
31 public DynamicApiActionInfo(
32 string actionName,
33 HttpVerb verb,
34 MethodInfo method,
35 IFilter[] filters = null,
36 bool? isApiExplorerEnabled = null)
37 {
38 ActionName = actionName;
39 Verb = verb;
40 Method = method;
41 IsApiExplorerEnabled = isApiExplorerEnabled;
42 Filters = filters ?? new IFilter[] { }; //Assigning or initialzing the action filters.
43 }
44 }
IApiControllerActionBuilder/ApiControllerActionBuilder:“ApiActionController”构建器,生成“DynamicApiActionInfo”对象;
DynamicApiControllerManager:ApiController管理类,以字典的形式,管理控制器。当浏览器接受到“HttpRouteData”请求时,程序根据服务的名称从该类中查找相应的controller;
DynamicHttpControllerDescriptor:继承自“HttpControllerDescriptor”;
AbpHttpControllerSelector:继承自“DefaultHttpControllerSelector”,重写了“SelectController”方法,返回新的“HttpControllerDescriptor”。在该类中,根据路由信息中的服务类名称,查找制定的“DynamicApiControllerInfo”;
AbpApiControllerActionSelector:继承自ASP.Net WebAPI 的 ApiControllerActionSelector,AbpApiControllerActionSelector 通过调用DynamicApiServiceNameHelper的静态方法(传入routedata中的serviceNameWithAction)获取action实例;
AbpApiControllerActivator :实现了 IHttpControllerActivator接口,根据controller的类型生成指定的controller;
AbpDynamicApiControllerInterceptor :方法拦截器,拦截“Action”请求,调用服务层中的方法。
try
{
invocation.ReturnValue=invocation.Method.Invoke(_proxiedObject, invocation.Arguments);
}
catch (TargetInvocationException targetInvocation)
{
if (targetInvocation.InnerException != null)
{
targetInvocation.InnerException.ReThrow();
}
throw;
}
拦截器在模块的初始化阶段注册:
1 public override void PostInitialize()
2 {
3 var httpConfiguration= IocManager.Resolve().HttpConfiguration;
4 InitializeRoutes(httpConfiguration);
5 InitializeAspNetServices(httpConfiguration);
6
7 foreach (var controllerInfo in IocManager.Resolve().GetAll())
8 {
9 IocManager.IocContainer.Register(
10 Component.For(controllerInfo.InterceptorType).LifestyleTransient(),
11 Component.For(controllerInfo.ApiControllerType)
12 .Proxy.AdditionalInterfaces(controllerInfo.ServiceInterfaceType)
13 .Interceptors(controllerInfo.InterceptorType)
14 .LifestyleTransient()
15 );
16
17 //LogHelper.Logger.DebugFormat("Dynamic web api controller is created for type ‘{0}‘ with service name ‘{1}‘.", controllerInfo.ServiceInterfaceType.FullName, controllerInfo.ServiceName);
18 }
19
20 Configuration.Modules.AbpWebApi().HttpConfiguration.EnsureInitialized();
21 //base.PostInitialize();
22 }
ABP动态生成WebAPI
标签:from common base ansi code webapi instance start containe
原文地址:https://www.cnblogs.com/SecondSun/p/9275184.html