

打造适用于c#的feign - KavinDavid
source link: https://www.cnblogs.com/pokemon/p/11412051.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

打造适用于c#的feign
之前因为工作原因使用spring cloud全家桶开发过若干项目,发现其中的feign非常好用,以前开发接口客户端的时候都是重复使用HttpClient实现业务,每次新增接口都十分繁琐,故萌生了自定义一个feign.net的想法,直到最近辞去工作后有了时间着手开发. 关于feign的介绍就不多说了,网上有大量的资料.
个人无太多精力复制feign的全部功能,只挑一些比较重要的来实现.
首先定义一个 FeignClientAttribute,其中的Fallback和FallbackFactory主要用于服务降级.
FeignClientAttribute
FeignClientLifetime为服务的生命周期
FeignClientLifetime
定义RequestMapping
RequestMappingAttribute
定义PathVariableAttribute等
PathVariableAttribute等
为了方便扩展,定义一个管道,里面包含了服务实例初始化,发送前,发送后等的事件.
FeignClientPipeline
基本的声明有了,然后开始实现动态生成代理类型代码.
先定义一个Proxy父类
View Code
ServiceDiscoveryHttpClientHandler
接下来开始生成代理类
TypeBuilder
CreateTypeBuilder
BuildConstructor
重写父类只读属性
BuildReadOnlyProperty
//serviceId BuildReadOnlyProperty(typeBuilder, serviceType, "ServiceId", serviceType.GetCustomAttribute<FeignClientAttribute>().Name); //baseUri BuildReadOnlyProperty(typeBuilder, serviceType, "BaseUri", serviceType.GetCustomAttribute<RequestMappingAttribute>()?.Value); // url if (serviceType.GetCustomAttribute<FeignClientAttribute>().Url != null) { BuildReadOnlyProperty(typeBuilder, serviceType, "Url", serviceType.GetCustomAttribute<FeignClientAttribute>().Url); } typeBuilder.AddInterfaceImplementation(serviceType);
接下来是最重要的,读取声明服务的所有方法,全部生成到代理类中
foreach (var method in serviceType.GetMethods()) { methodBuilder.BuildMethod(typeBuilder, serviceType, method, feignClientAttribute); }
View Code
最后看看效果
声明的服务
Service
生成的dll代码
Proxy Service
接下来测试一下
AddFeignClients
AddTestFeignClients
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); // services.AddDiscoveryClient(Configuration); services.AddFeignClients() .AddTestFeignClients() //.AddSteeltoeServiceDiscovery() ; }
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values/5 [HttpGet("{id}")] public async Task<ActionResult<object>> Get(int id, [FromServices] ITestService testService/*, [FromServices] ITestService1 testService1*/) { await testService.PostValueAsync(); //string html = await testService1.GetHtml(); //return html; //var rrr = typeof(Func<Task>).GetConstructors(System.Reflection.BindingFlags.Default); //IServiceCollection serviceCollection = HttpContext.RequestServices.GetService(typeof(IServiceCollection)) as IServiceCollection; //testService.GetValueVoidAsync(id, null, new TestServiceParam //{ // Name = "asasdsad" //}); //return await testService.GetValueAsync(id, "asdasd"); //await testService.PostValueForm2Async(id, "", new TestServiceParam //{ // Name = "testName" //}, new TestServiceParam //{ // Name = "name" //}); //testService.GetValueVoid(id, new TestServiceParam //{ // Name = "testName" //}, new TestServiceParam //{ // Name = "name" //}); //await testService.PostValueAsync(); //await testService.PostValueAsync(id, "", new TestServiceParam()); //return testService.GetQueryResultValue(id.ToString(), new TestServiceParam //{ // Name = "asasdsad" //}); //return await testService.GetQueryResultValueAsync(id.ToString(), new TestServiceParam //{ // Name = "asasdsad" //}); testService.GetValueVoidAsync(id, "", null); return "ok"; } }

正常工作了!
目前只支持简单的服务降级操作,没有实现Hystrix.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK