asp.net core mvc 之 DynamicApi
2021-02-01 12:15
标签:filter facet core stat array web odi tor nbsp 这段时间闲赋在家,感觉手痒,故想折腾一些东西. 由于之前移植了一个c#版本的spring cloud feign客户端(https://github.com/daixinkai/feign.net),所以想弄个配套的服务端动态接口,实现服务即接口的功能.虽然ABP框架内部包含一个功能强大的DynamicWebApi,但是我只是想要一个独立简单的组件,用来实现以下效果: 有一个业务服务 : 自动生成类似以下的接口 项目地址 : https://github.com/daixinkai/Microsoft.AspNetCore.Mvc.DynamicApi ------------------------------------------------------------------------------------------------- 首先定义一个DynamicApiAttribute,替代RouteAttribute的功能 思路就是查找标记了DynamicApiAttribute特性的接口,生成一个代理类型注册为控制器 1. BuildProxyType: 定义一个 TypeBuilder 先生成一个类型为当前接口类型的字段 : 生成构造函数,接收一个当前接口类型的对象,并赋值给上述字段 查找接口的所有方法,全部生成 最后别忘了复制特性 这样代理类型就生成完毕了 2.注册到Mvc框架中 由于默认ControllerFeatureProvider不支持生成的代理类型,需要自定义实现 这样就完成了,是不是很简单实用! 另外DynamicApi支持Mvc内置的Filter 3. 测试一下 最后别忘了注入服务 大功告成 asp.net core mvc 之 DynamicApi 标签:filter facet core stat array web odi tor nbsp 原文地址:https://www.cnblogs.com/pokemon/p/11596941.html public interface ITestService
{
Taskstring> GetName(int id);
}
[Route("api/test")]
public class TestController : ControllerBase
{
public TestController(ITestService testService)
{
_testService = testService;
}
ITestService _testService;
[HttpGet("name/{id}")]
public Taskstring> GetName(int id)
{
return _testService.GetName(id);
}
}
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class DynamicApiAttribute : Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider
{
public DynamicApiAttribute() { }
public DynamicApiAttribute(string template)
{
Template = template;
}
public string Template { get; set; }public int? Order { get; set; }
public string Name { get; set; }
}
FieldBuilder interfaceInstanceFieldBuilder = typeBuilder.DefineField("_interfaceInstance", interfaceType, FieldAttributes.Private);
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
new Type[] { interfaceType });
ILGenerator constructorIlGenerator = constructorBuilder.GetILGenerator();
constructorIlGenerator.Emit(OpCodes.Ldarg_0);
constructorIlGenerator.Emit(OpCodes.Ldarg_1);
constructorIlGenerator.Emit(OpCodes.Stfld, interfaceInstanceFieldBuilder);
constructorIlGenerator.Emit(OpCodes.Ret);
foreach (var method in interfaceType.GetMethodsIncludingBaseInterfaces())
{
BuildMethod(typeBuilder, interfaceType, method, interfaceInstanceFieldBuilder);
}
static void BuildMethod(TypeBuilder typeBuilder, Type interfaceType, MethodInfo method, FieldBuilder interfaceInstanceFieldBuilder)
{
MethodAttributes methodAttributes =
MethodAttributes.Public
| MethodAttributes.HideBySig
| MethodAttributes.NewSlot
| MethodAttributes.Virtual
| MethodAttributes.Final;
var parameters = method.GetParameters();
Type[] parameterTypes = parameters.Select(s => s.ParameterType).ToArray();
MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes, CallingConventions.Standard, method.ReturnType, parameterTypes);
#region parameterName
for (int i = 0; i )
{
methodBuilder.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Name);
}
#endregion
typeBuilder.DefineMethodOverride(methodBuilder, method);
ILGenerator iLGenerator = methodBuilder.GetILGenerator();
iLGenerator.Emit(OpCodes.Ldarg_0); // this
iLGenerator.Emit(OpCodes.Ldfld, interfaceInstanceFieldBuilder);
for (int i = 0; i )
{
iLGenerator.Emit(OpCodes.Ldarg_S, i + 1);
}
iLGenerator.Emit(OpCodes.Call, method);
iLGenerator.Emit(OpCodes.Ret);
var datas = CustomAttributeData.GetCustomAttributes(method);
foreach (var data in datas)
{
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(data.Constructor, data.ConstructorArguments.Select(s => s.Value).ToArray());
methodBuilder.SetCustomAttribute(customAttributeBuilder);
}
}
var datas = CustomAttributeData.GetCustomAttributes(interfaceType);
foreach (var data in datas)
{
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(data.Constructor, data.ConstructorArguments.Select(s => s.Value).ToArray());
typeBuilder.SetCustomAttribute(customAttributeBuilder);
}
public class DynamicApiControllerFeatureProvider : ControllerFeatureProvider
{
protected override bool IsController(TypeInfo typeInfo)
{
return typeInfo.IsProxyApi();
}
}
public static IMvcBuilder AddDynamicApi(this IMvcBuilder builder)
{
var feature = new ControllerFeature();
foreach (AssemblyPart assemblyPart in builder.PartManager.ApplicationParts.OfType())
{
foreach (var type in assemblyPart.Types)
{
if (type.IsInterface && type.IsDefinedIncludingBaseInterfaces
[DynamicApi("api/testService")]
public interface ITestService
{
//[Microsoft.AspNetCore.Authorization.Authorize]
[HttpGet("name/{id}")]
Taskstring> GetName(int id);
}
public class TestService : ITestService
{
public Taskstring> GetName(int id)
{
return Task.FromResult("Name" + id);
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddDynamicApi();
services.AddTransient
文章标题:asp.net core mvc 之 DynamicApi
文章链接:http://soscw.com/index.php/essay/49485.html