ABP之动态WebAPI

ABP之动态WebAPI

ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHandler一样),这样不仅减少了ApiController的开发,也更能体现驱动领域设计的层结构。

对WebApi服务的替换与路由配置

AbpWebApiModule是Abp.Web.Api的模块类,该类中定义InitializeAspNetServices,InitializeRoutes两个方法,并且在模块的Initialize方法中执行,这两个方法分别是对WebApi的服务的替换与路由的配置,。这两处对WebApi的变更才使得直接调用服务层成为可能。

 

对服务的分析与缓存

再对服务信息的存储上,作者提供了DynamicApiControllerInfo,DynamicApiActionInfo(源码中的DynamicApiMethodInfo.cs),其中DynamicApiControllerInfo包含了一DynamicApiActionInfo集合。

 

在执行AbpHttpControllerSelector, AbpApiControllerActionSelector, AbpControllerActivator的时候,系统已经在初始化的时候对服务层进行了分析与缓存。

在作者给的Demo SimpleTaskSystem下有一模块类SimpleTaskSystemWebApiModule


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

[DependsOn(typeof(AbpWebApiModule))] //We declare depended modules explicitly

public class SimpleTaskSystemWebApiModule : AbpModule

{

    public override void Initialize()

    {

        //This code is used to register classes to dependency injection system for this assembly using conventions.

        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

        //Creating dynamic Web Api Controllers for application services.

        //Thus, ‘web api layer‘ is created automatically by ABP.

        DynamicApiControllerBuilder

            .ForAll<IApplicationService>(Assembly.GetAssembly(typeof (SimpleTaskSystemApplicationModule)), "tasksystem")

            .Build();

    }

}

  

在这里是使用到了DynamicApiControllerBuilder,这个类主要是对服务接口进行一个注册,再由IBatchApiControllerBuilder按照注册的服务接口对提供的程序集进行分析。

DynamicApiControllerBuilder提供的ForAll只是返回的一个IBatchApiControllerBuilder实现对象


1

2

3

4

public static IBatchApiControllerBuilder<T> ForAll<T>(Assembly assembly, string servicePrefix)

{

    return new BatchApiControllerBuilder<T>(assembly, servicePrefix);

}

  

这个方法为BatchApiControllerBuilder提供了服务接口与服务接口与需要分析的程序集,以及服务地址前缀。

BatchApiControllerBuilder从程序集中获取实现服务接口的非抽象类。BatchApiControllerBuilder再通过DynamicApiControllerBuilder将这些类与服务名信息传递给IApiControllerBuilder。

+

  

IApiControllerBuilder将通过服务类生成DynamicApiControllerInfo,再将IApiControllerBuilder存储于DynamicApiControllerManager中,同时分析服务类,将公开非静态方法作为action,存储到DynamicApiControllerManager.Actions


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

internal class ApiControllerBuilder<T> : IApiControllerBuilder<T>

{

    /// <summary>

    /// Name of the controller.

    /// </summary>

    private readonly string _serviceName;

    /// <summary>

    /// List of all action builders for this controller.

    /// </summary>

    private readonly IDictionary<string, ApiControllerActionBuilder<T>> _actionBuilders;

    /// <summary>

    /// Action Filters to apply to the whole Dynamic Controller.

    /// </summary>

    private IFilter[] _filters;

    /// <summary>

    /// Creates a new instance of ApiControllerInfoBuilder.

    /// </summary>

    /// <param name="serviceName">Name of the controller</param>

    public ApiControllerBuilder(string serviceName)

    {

        if (string.IsNullOrWhiteSpace(serviceName))

        {

            throw new ArgumentException("serviceName null or empty!""serviceName");

        }

        if (!DynamicApiServiceNameHelper.IsValidServiceName(serviceName))

        {

            throw new ArgumentException("serviceName is not properly formatted! It must contain a single-depth namespace at least! For example: ‘myapplication/myservice‘.""serviceName");

        }

        _serviceName = serviceName;

        _actionBuilders = new Dictionary<string, ApiControllerActionBuilder<T>>();

        foreach (var methodInfo in DynamicApiControllerActionHelper.GetMethodsOfType(typeof(T)))

        {

            _actionBuilders[methodInfo.Name] = new ApiControllerActionBuilder<T>(this, methodInfo);

        }

    }

    /// <summary>

    /// The adds Action filters for the whole Dynamic Controller

    /// </summary>

    /// <param name="filters"> The filters. </param>

    /// <returns>The current Controller Builder </returns>

    public IApiControllerBuilder<T> WithFilters(params IFilter[] filters)

    {

        _filters = filters;

        return this;

    }

    /// <summary>

    /// Used to specify a method definition.

    /// </summary>

    /// <param name="methodName">Name of the method in proxied type</param>

    /// <returns>Action builder</returns>

    public IApiControllerActionBuilder<T> ForMethod(string methodName)

    {

        if (!_actionBuilders.ContainsKey(methodName))

        {

            throw new AbpException("There is no method with name " + methodName + " in type " typeof(T).Name);

        }

        return _actionBuilders[methodName];

    }

    /// <summary>

    /// Builds the controller.

    /// This method must be called at last of the build operation.

    /// </summary>

    public void Build()

    {

        var controllerInfo = new DynamicApiControllerInfo(_serviceName, typeof(DynamicApiController<T>), _filters);

        

        foreach (var actionBuilder in _actionBuilders.Values)

        {

            if (actionBuilder.DontCreate)

            {

                continue;

            }

            controllerInfo.Actions[actionBuilder.ActionName] = actionBuilder.BuildActionInfo();

        }

        IocManager.Instance.IocContainer.Register(

            Component.For<AbpDynamicApiControllerInterceptor<T>>().LifestyleTransient(),

            Component.For<DynamicApiController<T>>().Proxy.AdditionalInterfaces(new[] { typeof(T) }).Interceptors<AbpDynamicApiControllerInterceptor<T>>().LifestyleTransient()

            );

        DynamicApiControllerManager.Register(controllerInfo);

        LogHelper.Logger.DebugFormat("Dynamic web api controller is created for type ‘{0}‘ with service name ‘{1}‘."typeof(T).FullName, controllerInfo.ServiceName);

    }

}

  

时间: 2024-10-12 16:42:42

ABP之动态WebAPI的相关文章

ABP中动态WebAPI原理解析

ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能,这应该算是对DRY的最佳诠释了. 如下图所示,一行代码就为所有实现了IApplicationService的类型,自动创建对应的动态WebAPI. 这么Magic的功能是如何实现的呢? 本文为你揭开其Magic的外表.你会发现,实现如此Magic的功能,最关键的代码

ABP源码分析三十五:ABP中动态WebAPI原理解析

动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能,这应该算是对DRY的最佳诠释了. 如下图所示,一行代码就为所有实现了IApplicationService的类型,自动创建对应的动态WebAPI. 这么Magic的功能是如何实现的呢? 本文为你揭开其Magic的外表.你会发现,实现如此Magic的功能,最关键的代码只有四行. 先思考一个问题:如果不

ABP之动态WebAPI(二)

HttpControllerDescriptor与HttpActionDescriptor HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以将它视为某个HttpController类型的描述对象.HttpActionDescriptor也类似.上一篇中说到Abp将ApiControler与Action信息分别封装于DynamicApiControllerInfo,DynamicApiActionInfo.Abp种HttpControll

Asp.Net Core 3.1 Api 集成Abp项目动态WebApi

上一节讲到了abp的依赖注入,其实我们用webapi时,控制器的代码几乎都是多余的,abp为我们提供了Application层动态生成WebApi接口的功能 我们在ApiHost 项目安装 Swashbuckle.AspNetCore Nuget Package 5.0.0 在Startup中使用它, 访问项目路径加上/Swagger回车就可以看到接口了 但是现在Application的方法还没有动态生成WebApi 我们加入“用Application项目创建webapi控制器的代码” ,但是这

ABP之动态WebAPI(一)

ABP在与页面交互中最.它让我们可以直接可以调用服务层(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHandler一样),这样不仅减少了ApiController的开发,也更能体现驱动领域设计的层结构. 对WebApi服务的替换与路由配置 AbpWebApiModule是Abp.Web.Api的模块类,该类中定义InitializeAspNetServices,InitializeRoutes两个

【5000 Stars 福利】微信接口动态 WebApi 使用说明

前言 作为中国 C# 开源项目中 Watch/Star/Fork 最高的项目之一,Senparc.Weixin SDK  凝聚了盛派微信团队持续7年的付出,和大量开发者的无私贡献,以及数万开发者的使用与反馈.为了纪念 Senparc.Weixin SDK 项目突破 5000 Stars 这个小小的里程碑,盛派微信团队为大家准备了一份特殊福利:微信接口动态 WebApi 系统(以下简称“系统”),在此系统中,您可以使用 WebApi 调用 Senparc.Weixin SDK 已经集成的微信高级接

&lt;&lt;ABP框架&gt;&gt; 动态Web Api层

文档目录 本节内容: 创建动态Web Api控制器 ForAll 方法 重写 ForAll ForMethods Http 动词 WithVerb 方法 HTTP 特性 命名约定 Api 浏览器 RemoteService 特性 动态Javascript代理 AJAX 参数 单独服务脚本 Angular 集成 启用/禁用 包装结果 关于参数绑定 FormUri 和 FormBody 特性 DTO vs 简单类型 创建动态Web Api 控制器 这个文档是关于Asp.net Web Api的,如果

ASP.NET ABP 之动态Web API层

建立动态Web API 控制器 ASP.NET Boilerplate 能够自动为您的应用层产生Web API层.比如说我们有如下的一个应用服务: 1 public interface ITaskAppService : IApplicationService 2 { 3 GetTasksOutput GetTasks(GetTasksInput input); 4 void UpdateTask(UpdateTaskInput input); 5 void CreateTask(CreateT

abp添加动态菜单

abp中MenuDefinition封装了导航栏上的主菜单的属性,MenuItemDefinition则封装了子菜单的属性,子菜单可以引用其他子菜单构成一个菜单树. MenuDefinitio成员如下: public object CustomData { get; set; }//自定义数据 public ILocalizableString DisplayName { get; set; }//表示本地化字符串 public IList<MenuItemDefinition> Items