Skip to content

Commit 692d819

Browse files
committed
增加HttpApiProxyActivator抽象类
1 parent e087826 commit 692d819

File tree

5 files changed

+264
-226
lines changed

5 files changed

+264
-226
lines changed

WebApiClientCore/ApiActionDescriptor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ public class ApiActionDescriptor
7171
/// <param name="method">接口的方法</param>
7272
/// <param name="interfaceType">接口类型</param>
7373
/// <exception cref="ArgumentNullException"></exception>
74-
/// <exception cref="ArgumentException"></exception>
7574
public ApiActionDescriptor(MethodInfo method, Type? interfaceType = default)
7675
{
7776
if (method == null)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace WebApiClientCore
5+
{
6+
/// <summary>
7+
/// 表示THttpApi的代理类的实例创建器抽象
8+
/// </summary>
9+
/// <typeparam name="THttpApi"></typeparam>
10+
abstract class HttpApiProxyActivator<THttpApi>
11+
{
12+
/// <summary>
13+
/// 实例工厂
14+
/// </summary>
15+
private readonly Func<IActionInterceptor, THttpApi> factory;
16+
17+
/// <summary>
18+
/// THttpApi的代理类的实例创建器
19+
/// </summary>
20+
public HttpApiProxyActivator()
21+
{
22+
this.factory = this.CreateFactory();
23+
}
24+
25+
/// <summary>
26+
/// 创建代理类的实例工厂
27+
/// </summary>
28+
/// <returns></returns>
29+
protected abstract Func<IActionInterceptor, THttpApi> CreateFactory();
30+
31+
/// <summary>
32+
/// 实例代理类的实例
33+
/// </summary>
34+
/// <param name="interceptor">拦截器</param>
35+
/// <returns></returns>
36+
public THttpApi CreateInstance(IActionInterceptor interceptor)
37+
{
38+
return this.factory(interceptor);
39+
}
40+
41+
/// <summary>
42+
/// 返回接口的action执行器
43+
/// </summary>
44+
/// <exception cref="NotSupportedException"></exception>
45+
/// <returns></returns>
46+
protected IActionInvoker[] GetActionInvokers()
47+
{
48+
var interfaceType = typeof(THttpApi);
49+
return interfaceType
50+
.GetAllApiMethods()
51+
.Select(item => new ApiActionDescriptor(item, interfaceType))
52+
.Select(item => CreateActionInvoker(item))
53+
.ToArray();
54+
}
55+
56+
/// <summary>
57+
/// 创建Action执行器
58+
/// </summary>
59+
/// <param name="apiAction">action描述</param>
60+
/// <returns></returns>
61+
private static IActionInvoker CreateActionInvoker(ApiActionDescriptor apiAction)
62+
{
63+
var resultType = apiAction.Return.DataType.Type;
64+
var invokerType = typeof(MultiplexedActionInvoker<>).MakeGenericType(resultType);
65+
return invokerType.CreateInstance<IActionInvoker>(apiAction);
66+
}
67+
}
68+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reflection;
4+
using System.Reflection.Emit;
5+
using WebApiClientCore.Exceptions;
6+
7+
namespace WebApiClientCore
8+
{
9+
/// <summary>
10+
/// 表示Emit方式的THttpApi的代理类的实例创建器
11+
/// </summary>
12+
/// <typeparam name="THttpApi"></typeparam>
13+
class HttpApiProxyEmitActivator<THttpApi> : HttpApiProxyActivator<THttpApi>
14+
{
15+
/// <summary>
16+
/// 创建代理类的实例工厂
17+
/// </summary>
18+
/// <returns></returns>
19+
protected override Func<IActionInterceptor, THttpApi> CreateFactory()
20+
{
21+
var actionInvokers = this.GetActionInvokers();
22+
var proxyType = ProxyTypeBuilder.Build(typeof(THttpApi), actionInvokers);
23+
var proxyTypeCtor = Lambda.CreateCtorFunc<IActionInterceptor, IActionInvoker[], THttpApi>(proxyType);
24+
return (interceptor) => proxyTypeCtor(interceptor, actionInvokers);
25+
}
26+
27+
/// <summary>
28+
/// 提供IHttpApi代理类的类型创建
29+
/// </summary>
30+
private static class ProxyTypeBuilder
31+
{
32+
/// <summary>
33+
/// IActionInterceptor的Intercept方法
34+
/// </summary>
35+
private static readonly MethodInfo interceptMethod = typeof(IActionInterceptor).GetMethod(nameof(IActionInterceptor.Intercept)) ?? throw new MissingMethodException(nameof(IActionInterceptor.Intercept));
36+
37+
/// <summary>
38+
/// 代理类型的构造器的参数类型
39+
/// (IApiInterceptor interceptor,IActionInvoker[] actionInvokers)
40+
/// </summary>
41+
private static readonly Type[] proxyTypeCtorArgTypes = new Type[] { typeof(IActionInterceptor), typeof(IActionInvoker[]) };
42+
43+
/// <summary>
44+
/// 创建IHttpApi代理类的类型
45+
/// </summary>
46+
/// <param name="interfaceType">接口类型</param>
47+
/// <param name="actionInvokers">action执行器</param>
48+
/// <exception cref="NotSupportedException"></exception>
49+
/// <exception cref="ProxyTypeCreateException"></exception>
50+
/// <returns></returns>
51+
public static Type Build(Type interfaceType, IActionInvoker[] actionInvokers)
52+
{
53+
// 接口的实现在动态程序集里,所以接口必须为public修饰才可以创建代理类并实现此接口
54+
if (interfaceType.IsVisible == false)
55+
{
56+
var message = Resx.required_PublicInterface.Format(interfaceType);
57+
throw new NotSupportedException(message);
58+
}
59+
60+
var moduleName = interfaceType.Module.Name;
61+
var assemblyName = new AssemblyName(Guid.NewGuid().ToString());
62+
63+
var module = AssemblyBuilder
64+
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run)
65+
.DefineDynamicModule(moduleName);
66+
67+
var typeName = interfaceType.FullName ?? Guid.NewGuid().ToString();
68+
var builder = module.DefineType(typeName, TypeAttributes.Class);
69+
builder.AddInterfaceImplementation(interfaceType);
70+
71+
var fieldActionInterceptor = BuildField(builder, "<>actionInterceptor", typeof(IActionInterceptor));
72+
var fieldActionInvokers = BuildField(builder, "<>actionInvokers", typeof(IActionInvoker[]));
73+
74+
BuildCtor(builder, fieldActionInterceptor, fieldActionInvokers);
75+
BuildMethods(builder, actionInvokers, fieldActionInterceptor, fieldActionInvokers);
76+
77+
var proxyType = builder.CreateType();
78+
return proxyType ?? throw new ProxyTypeCreateException(interfaceType);
79+
}
80+
81+
/// <summary>
82+
/// 生成代理类型的字段
83+
/// </summary>
84+
/// <param name="builder">类型生成器</param>
85+
/// <param name="fieldName">字段名称</param>
86+
/// <param name="fieldType">字段类型</param>
87+
/// <returns></returns>
88+
private static FieldBuilder BuildField(TypeBuilder builder, string fieldName, Type fieldType)
89+
{
90+
const FieldAttributes filedAttribute = FieldAttributes.Private | FieldAttributes.InitOnly;
91+
return builder.DefineField(fieldName, fieldType, filedAttribute);
92+
}
93+
94+
/// <summary>
95+
/// 生成代理类型的构造器
96+
/// </summary>
97+
/// <param name="builder">类型生成器</param>
98+
/// <param name="fieldActionInterceptor">拦截器字段</param>
99+
/// <param name="fieldActionInvokers">action执行器字段</param>
100+
/// <returns></returns>
101+
private static void BuildCtor(TypeBuilder builder, FieldBuilder fieldActionInterceptor, FieldBuilder fieldActionInvokers)
102+
{
103+
// .ctor(IApiInterceptor actionInterceptor, IActionInvoker[] actionInvokers)
104+
var ctor = builder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, proxyTypeCtorArgTypes);
105+
106+
var il = ctor.GetILGenerator();
107+
108+
// this.actionInterceptor = 第一个参数
109+
il.Emit(OpCodes.Ldarg_0);
110+
il.Emit(OpCodes.Ldarg_1);
111+
il.Emit(OpCodes.Stfld, fieldActionInterceptor);
112+
113+
// this.actionInvokers = 第二个参数
114+
il.Emit(OpCodes.Ldarg_0);
115+
il.Emit(OpCodes.Ldarg_2);
116+
il.Emit(OpCodes.Stfld, fieldActionInvokers);
117+
118+
il.Emit(OpCodes.Ret);
119+
}
120+
121+
/// <summary>
122+
/// 生成代理类型的接口实现方法
123+
/// </summary>
124+
/// <param name="builder">类型生成器</param>
125+
/// <param name="actionInvokers">action执行器</param>
126+
/// <param name="fieldActionInterceptor">拦截器字段</param>
127+
/// <param name="fieldActionInvokers">action执行器字段</param>
128+
private static void BuildMethods(TypeBuilder builder, IActionInvoker[] actionInvokers, FieldBuilder fieldActionInterceptor, FieldBuilder fieldActionInvokers)
129+
{
130+
const MethodAttributes implementAttribute = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.HideBySig;
131+
132+
for (var i = 0; i < actionInvokers.Length; i++)
133+
{
134+
var actionMethod = actionInvokers[i].ApiAction.Member;
135+
var actionParameters = actionMethod.GetParameters();
136+
var parameterTypes = actionParameters.Select(p => p.ParameterType).ToArray();
137+
138+
var iL = builder
139+
.DefineMethod(actionMethod.Name, implementAttribute, CallingConventions.Standard, actionMethod.ReturnType, parameterTypes)
140+
.GetILGenerator();
141+
142+
// this.actionInterceptor
143+
iL.Emit(OpCodes.Ldarg_0);
144+
iL.Emit(OpCodes.Ldfld, fieldActionInterceptor);
145+
146+
// this.actionInvokers[i]
147+
iL.Emit(OpCodes.Ldarg_0);
148+
iL.Emit(OpCodes.Ldfld, fieldActionInvokers);
149+
iL.Emit(OpCodes.Ldc_I4, i);
150+
iL.Emit(OpCodes.Ldelem_Ref);
151+
152+
// var arguments = new object[parameters.Length]
153+
var arguments = iL.DeclareLocal(typeof(object[]));
154+
iL.Emit(OpCodes.Ldc_I4, actionParameters.Length);
155+
iL.Emit(OpCodes.Newarr, typeof(object));
156+
iL.Emit(OpCodes.Stloc, arguments);
157+
158+
for (var j = 0; j < actionParameters.Length; j++)
159+
{
160+
iL.Emit(OpCodes.Ldloc, arguments);
161+
iL.Emit(OpCodes.Ldc_I4, j);
162+
iL.Emit(OpCodes.Ldarg, j + 1);
163+
164+
var parameterType = parameterTypes[j];
165+
if (parameterType.IsValueType || parameterType.IsGenericParameter)
166+
{
167+
iL.Emit(OpCodes.Box, parameterType);
168+
}
169+
iL.Emit(OpCodes.Stelem_Ref);
170+
}
171+
172+
// 加载arguments参数
173+
iL.Emit(OpCodes.Ldloc, arguments);
174+
175+
// Intercep(actionInvoker, arguments)
176+
iL.Emit(OpCodes.Callvirt, interceptMethod);
177+
178+
if (actionMethod.ReturnType == typeof(void))
179+
{
180+
iL.Emit(OpCodes.Pop);
181+
}
182+
183+
iL.Emit(OpCodes.Castclass, actionMethod.ReturnType);
184+
iL.Emit(OpCodes.Ret);
185+
}
186+
}
187+
}
188+
}
189+
}
Lines changed: 7 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Linq;
32
using System.Threading;
43
using WebApiClientCore.Exceptions;
54

@@ -12,56 +11,9 @@ namespace WebApiClientCore
1211
class HttpApiProxyFactory<THttpApi>
1312
{
1413
/// <summary>
15-
/// 接口包含的所有action执行器
14+
/// 代理实例创建者
1615
/// </summary>
17-
private readonly IActionInvoker[] actionInvokers;
18-
19-
/// <summary>
20-
/// 接口代理类的构造器
21-
/// </summary>
22-
private readonly Func<IActionInterceptor, IActionInvoker[], THttpApi> proxyTypeCtor;
23-
24-
/// <summary>
25-
/// 表示THttpApi的代理类的创建工厂
26-
/// </summary>
27-
/// <exception cref="NotSupportedException"></exception>
28-
/// <exception cref="ProxyTypeCreateException"></exception>
29-
private HttpApiProxyFactory()
30-
{
31-
var interfaceType = typeof(THttpApi);
32-
33-
this.actionInvokers = interfaceType
34-
.GetAllApiMethods()
35-
.Select(item => new ApiActionDescriptor(item, interfaceType))
36-
.Select(item => CreateActionInvoker(item))
37-
.ToArray();
38-
39-
var proxyType = HttpApiProxyTypeBuilder.Build(interfaceType, this.actionInvokers);
40-
this.proxyTypeCtor = Lambda.CreateCtorFunc<IActionInterceptor, IActionInvoker[], THttpApi>(proxyType);
41-
42-
static IActionInvoker CreateActionInvoker(ApiActionDescriptor apiAction)
43-
{
44-
var resultType = apiAction.Return.DataType.Type;
45-
var invokerType = typeof(MultiplexedActionInvoker<>).MakeGenericType(resultType);
46-
return invokerType.CreateInstance<IActionInvoker>(apiAction);
47-
}
48-
}
49-
50-
/// <summary>
51-
/// 创建代理类的实例
52-
/// </summary>
53-
/// <param name="actionInterceptor">拦截器</param>
54-
/// <returns></returns>
55-
private THttpApi CreateProxy(IActionInterceptor actionInterceptor)
56-
{
57-
return this.proxyTypeCtor.Invoke(actionInterceptor, this.actionInvokers);
58-
}
59-
60-
61-
/// <summary>
62-
/// 代理创建工厂的实例
63-
/// </summary>
64-
private static HttpApiProxyFactory<THttpApi>? instance;
16+
private static HttpApiProxyActivator<THttpApi>? _activator;
6517

6618
/// <summary>
6719
/// 创建代理类的实例
@@ -72,14 +24,14 @@ private THttpApi CreateProxy(IActionInterceptor actionInterceptor)
7224
/// <returns></returns>
7325
public static THttpApi Create(IActionInterceptor actionInterceptor)
7426
{
75-
var fatory = Volatile.Read(ref instance);
76-
if (fatory == null)
27+
var activator = Volatile.Read(ref _activator);
28+
if (activator == null)
7729
{
78-
Interlocked.CompareExchange(ref instance, new HttpApiProxyFactory<THttpApi>(), null);
79-
fatory = instance;
30+
Interlocked.CompareExchange(ref _activator, new HttpApiProxyEmitActivator<THttpApi>(), null);
31+
activator = _activator;
8032
}
8133

82-
return fatory.CreateProxy(actionInterceptor);
34+
return activator.CreateInstance(actionInterceptor);
8335
}
8436
}
8537
}

0 commit comments

Comments
 (0)