Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions WebApiClientCore.Analyzers/SourceGenerator/HttpApiProxyClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,41 +103,32 @@ public override string ToString()
builder.AppendLine();

var index = 0;
foreach (var method in this.FindApiMethods())
foreach (var interfaceType in this.httpApi.AllInterfaces.Append(httpApi))
{
var methodCode = this.BuildMethod(method, index);
builder.AppendLine(methodCode);
index += 1;
foreach (var method in interfaceType.GetMembers().OfType<IMethodSymbol>())
{
var methodCode = this.BuildMethod(interfaceType, method, index);
builder.AppendLine(methodCode);
index += 1;
}
}


builder.AppendLine("\t}");
builder.AppendLine("}");
builder.AppendLine("#pragma warning restore");

return builder.ToString();
}

/// <summary>
/// 查找接口类型及其继承的接口的所有方法
/// </summary>
/// <returns></returns>
private IEnumerable<IMethodSymbol> FindApiMethods()
{
#pragma warning disable RS1024
return this.httpApi.AllInterfaces.Append(httpApi)
.SelectMany(item => item.GetMembers())
.OfType<IMethodSymbol>()
.Distinct(MethodEqualityComparer.Default);
#pragma warning restore RS1024
}

/// <summary>
/// 构建方法
/// </summary>
/// <param name="interfaceType"></param>
/// <param name="method"></param>
/// <param name="index"></param>
/// <returns></returns>
private string BuildMethod(IMethodSymbol method, int index)
private string BuildMethod(INamedTypeSymbol interfaceType, IMethodSymbol method, int index)
{
var builder = new StringBuilder();
var parametersString = string.Join(",", method.Parameters.Select(item => $"{GetFullName(item.Type)} {item.Name}"));
Expand All @@ -146,9 +137,10 @@ private string BuildMethod(IMethodSymbol method, int index)
? "global::System.Array.Empty<global::System.Object>()"
: $"new global::System.Object[] {{ {parameterNamesString} }}";

var methodName = $"\"{interfaceType.ToDisplayString()}.{method.Name}\"";
var returnTypeString = GetFullName(method.ReturnType);
builder.AppendLine($"\t\t[global::WebApiClientCore.HttpApiProxyMethod({index})]");
builder.AppendLine($"\t\tpublic {returnTypeString} {method.Name}( {parametersString} )");
builder.AppendLine($"\t\t[global::WebApiClientCore.HttpApiProxyMethod({index}, {methodName})]");
builder.AppendLine($"\t\t{returnTypeString} {GetFullName(interfaceType)}.{method.Name}( {parametersString} )");
builder.AppendLine("\t\t{");
builder.AppendLine($"\t\t\treturn ({returnTypeString})this.{this.apiInterceptorFieldName}.Intercept(this.{this.actionInvokersFieldName}[{index}], {paremterArrayString});");
builder.AppendLine("\t\t}");
Expand Down
7 changes: 4 additions & 3 deletions WebApiClientCore.Test/HttpApiTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Xunit;

namespace WebApiClientCore.Test
Expand Down Expand Up @@ -39,11 +40,11 @@ public void GetAllApiMethodsTest()
var m2 = HttpApi.FindApiMethods(typeof(IMyApi));

Assert.False(object.ReferenceEquals(m1, m2));
Assert.True(m1.Length == 3);
Assert.Equal(3, m1.Length);

var m3 = HttpApi.FindApiMethods(typeof(IPostNew));
Assert.Single(m3);
Assert.True(m3[0].IsDefined(typeof(NewAttribute), true));
Assert.Equal(2, m3.Length);
Assert.Contains(m3, i => i.IsDefined(typeof(NewAttribute), true));
}
}
}
12 changes: 3 additions & 9 deletions WebApiClientCore/Exceptions/ProxyTypeCreateException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ namespace WebApiClientCore.Exceptions
/// <summary>
/// 表示代理类创建异常
/// </summary>
public class ProxyTypeCreateException : Exception
public class ProxyTypeCreateException : ProxyTypeException
{
/// <summary>
/// 接口类型
/// </summary>
public Type InterfaceType { get; }

/// <summary>
/// 代理类创建异常
/// </summary>
/// <param name="interfaceType">接口类型</param>
public ProxyTypeCreateException(Type interfaceType)
: this(interfaceType, null)
: base(interfaceType)
{
}

Expand All @@ -27,9 +22,8 @@ public ProxyTypeCreateException(Type interfaceType)
/// <param name="interfaceType">接口类型</param>
/// <param name="message">提示消息</param>
public ProxyTypeCreateException(Type interfaceType, string? message)
: base(message)
: base(interfaceType, message)
{
this.InterfaceType = interfaceType;
}
}
}
35 changes: 35 additions & 0 deletions WebApiClientCore/Exceptions/ProxyTypeException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;

namespace WebApiClientCore.Exceptions
{
/// <summary>
/// 表示代理类异常
/// </summary>
public class ProxyTypeException : Exception
{
/// <summary>
/// 接口类型
/// </summary>
public Type InterfaceType { get; }

/// <summary>
/// 代理类异常
/// </summary>
/// <param name="interfaceType">接口类型</param>
public ProxyTypeException(Type interfaceType)
: this(interfaceType, null)
{
}

/// <summary>
/// 代理类创建异常
/// </summary>
/// <param name="interfaceType">接口类型</param>
/// <param name="message">提示消息</param>
public ProxyTypeException(Type interfaceType, string? message)
: base(message)
{
this.InterfaceType = interfaceType;
}
}
}
4 changes: 2 additions & 2 deletions WebApiClientCore/HttpApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ public static MethodInfo[] FindApiMethods(Type httpApiType)
throw new ArgumentException(Resx.required_InterfaceType.Format(httpApiType.Name));
}

return HttpApiMethodFinder
.FindApiMethods(httpApiType)
return httpApiType.GetInterfaces().Append(httpApiType)
.SelectMany(item => item.GetMethods())
.Select(item => item.EnsureApiMethod())
.ToArray();
}
Expand Down
121 changes: 0 additions & 121 deletions WebApiClientCore/HttpApiMethodFinder.cs

This file was deleted.

9 changes: 8 additions & 1 deletion WebApiClientCore/HttpApiProxyMethodAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ public sealed class HttpApiProxyMethodAttribute : Attribute
/// </summary>
public int Index { get; }

/// <summary>
/// 获取名称
/// </summary>
public string Name { get; }

/// <summary>
/// 方法的索引特性
/// </summary>
/// <param name="index">索引值,确保连续且不重复</param>
public HttpApiProxyMethodAttribute(int index)
/// <param name="name">方法的名称</param>
public HttpApiProxyMethodAttribute(int index, string name)
{
this.Index = index;
this.Name = name;
}
}
}
14 changes: 8 additions & 6 deletions WebApiClientCore/Implementations/EmitHttpApiActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class EmitHttpApiActivator<
#if NET5_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
#endif
THttpApi> : IHttpApiActivator<THttpApi>
THttpApi> : IHttpApiActivator<THttpApi>
{
private readonly ApiActionInvoker[] actionInvokers;
private readonly Func<IHttpApiInterceptor, ApiActionInvoker[], THttpApi> activator;
Expand All @@ -33,7 +33,7 @@ public EmitHttpApiActivator(IApiActionDescriptorProvider apiActionDescriptorProv

this.actionInvokers = apiMethods
.Select(item => apiActionDescriptorProvider.CreateActionDescriptor(item, typeof(THttpApi)))
.Select(item => actionInvokerProvider.CreateActionInvoker(item))
.Select(actionInvokerProvider.CreateActionInvoker)
.ToArray();

var proxyType = BuildProxyType(typeof(THttpApi), apiMethods);
Expand Down Expand Up @@ -151,17 +151,19 @@ private static void BuildCtor(TypeBuilder builder, FieldBuilder fieldApiIntercep
/// <param name="fieldActionInvokers">action执行器字段</param>
private static void BuildMethods(TypeBuilder builder, MethodInfo[] actionMethods, FieldBuilder fieldApiInterceptor, FieldBuilder fieldActionInvokers)
{
const MethodAttributes implementAttribute = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.HideBySig;
// private final hidebysig newslot virtual
const MethodAttributes implementAttribute = MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;

for (var i = 0; i < actionMethods.Length; i++)
{
var actionMethod = actionMethods[i];
var actionParameters = actionMethod.GetParameters();
var parameterTypes = actionParameters.Select(p => p.ParameterType).ToArray();
var actionMethodName = $"{actionMethod.DeclaringType?.FullName}.{actionMethod.Name}";

var iL = builder
.DefineMethod(actionMethod.Name, implementAttribute, CallingConventions.Standard, actionMethod.ReturnType, parameterTypes)
.GetILGenerator();
var methodBuilder = builder.DefineMethod(actionMethodName, implementAttribute, CallingConventions.Standard | CallingConventions.HasThis, actionMethod.ReturnType, parameterTypes);
builder.DefineMethodOverride(methodBuilder, actionMethod);
var iL = methodBuilder.GetILGenerator();

// this.apiInterceptor
iL.Emit(OpCodes.Ldarg_0);
Expand Down
Loading