Skip to content

Commit

Permalink
Merge pull request #256 from dotnetcore/override
Browse files Browse the repository at this point in the history
Override
  • Loading branch information
xljiulang authored Jun 5, 2024
2 parents aa56411 + 3a2c9da commit cd18440
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 221 deletions.
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

0 comments on commit cd18440

Please sign in to comment.