ABP框架可以动态生成WebApi,开发人员无需创建APIController,直接继承IApplicationService接口,即可对外发布webApi。

创建动态Web Api 控制器


例如,在Service层有一个ITestService接口,如下:

public interface ITestService : IApplicationService
    {
        List<int> 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<T>:动态生成ApiController类,继承自“AbpApiController”,“IDynamicApiController”;

1  public class DynamicApiController<T>: AbpApiController, IDynamicApiController
2     {
3         public List<string> AppliedCrossCuttingConcerns { get; }
4         public DynamicApiController()
5         {
6             AppliedCrossCuttingConcerns = new List<string>();
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 Dictionary<string, DynamicApiActionInfo>(StringComparer.InvariantCultureIgnoreCase);
18         }

 

IBatchApiControllerBuilder<T>/BatchApiControllerBuilder<T>:批量ApiController构建器,通过“Build”方法,根据程序集,批量生成“DynamicApiControllerInfo”;

 internal class BatchApiControllerBuilder<T> : IBatchApiControllerBuilder<T>
    {
        #region 声明实例
        private readonly string _servicePrefix;
        private readonly Assembly _assembly;
        private IFilter[] _filters;
        private Func<Type, string> _serviceNameSelector;
        private Func<Type, bool> _typePredicate;
        private bool _conventionalVerbs;
        private Action<IApiControllerActionBuilder<T>> _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<T> ForMethods(Action<IApiControllerActionBuilder> action)
        {
            _forMethodsAction = action;
            return this;
        }

        public IBatchApiControllerBuilder<T> Where(Func<Type, bool> predicate)
        {
            _typePredicate = predicate;
            return this;

        }

        public IBatchApiControllerBuilder<T> WithApiExplorer(bool isEnabled)
        {
            _isApiExplorerEnabled = isEnabled;
            return this;
        }

        public IBatchApiControllerBuilder<T> WithConventionalVerbs()
        {
            _conventionalVerbs = true;
            return this;
        }

        public IBatchApiControllerBuilder<T> WithFilters(params IFilter[] filters)
        {
            _filters = filters;
            return this;
        }

        public IBatchApiControllerBuilder<T> WithProxyScripts(bool isEnabled)
        {
            _isProxyScriptingEnabled = isEnabled;
            return this;
        }

        public IBatchApiControllerBuilder<T> WithServiceName(Func<Type, string> serviceNameSelector)
        {
            _serviceNameSelector = serviceNameSelector;
            return this;
        }
        #endregion
    }
View Code

相关文章:

  • 2022-12-23
  • 2021-07-13
  • 2022-12-23
  • 2022-12-23
  • 2022-01-20
  • 2022-02-02
  • 2021-11-11
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-10
  • 2022-02-21
  • 2022-02-17
  • 2022-12-23
相关资源
相似解决方案