如何将.NET Core微服务的另一种实现方法转化为长尾关键词?
- 内容介绍
- 文章标签
- 相关推荐
本文共计974个文字,预计阅读时间需要4分钟。
前言:基于.net core的微服务,网上很多介绍都是千篇一律,基于类似webapi的示例,通过http请求形式进行访问,但这并不符合大型企业使用习惯。如何像[GetServiceIOrderService]().SaveOrder(orderInfo)这样的方式,直接调用,提高开发效率?
结果:探讨如何实现类似[GetServiceIOrderService]().SaveOrder(orderInfo)的直接调用方式,提高微服务开发效率。
前言
基于.net core 的微服务,网上很多介绍都是千篇一律基于类似webapi,通过localhost:8801/api/svc" }, { "ServiceId": "XZL.Api.IUserService", "Address": "localhost:8802/api/svc" } ]
AppRuntime.Instance.GetService<TService>()的实现.
private static List<(string typeName, Type svcType)> svcTypeDic; private static ConcurrentDictionary<string, Object> svcInstance = new ConcurrentDictionary<string, object>(); public static TService GetService<TService>() { var serviceId = typeof(TService).FullName; //读取服务配置 var serviceInfo = ServiceConfonfig.Instance.GetServiceInfo(serviceId); if (serviceInfo == null) { return (TService)Activator.CreateInstance(GetSvcType(serviceId)); } else { var rs = GetService<TService>(serviceId + (serviceInfo.IsRemote ? "|Remote" : ""), serviceInfo.IsSingle); if (rs != null && rs is RemoteServiceProxy) { var temp = rs as RemoteServiceProxy; temp.Address = serviceInfo.Address; //指定服务地址 } return rs; } } public static TService GetService<TService>(string interfaceId, bool isSingle) { //服务非单例模式 if (!isSingle) { return (TService)Activator.CreateInstance(GetSvcType(interfaceId)); } object obj = null; if (svcInstance.TryGetValue(interfaceId, out obj) && obj != null) { return (TService)obj; } var svcType = GetSvcType(interfaceId); if (svcType == null) { throw new ICVIPException($"系统中未找到[{interfaceId}]的代理类"); } obj = Activator.CreateInstance(svcType); svcInstance.TryAdd(interfaceId, obj); return (TService)obj; } //获取服务的实现类 public static Type GetSvcType(string interfaceId, bool? isLocal = null) { if (!_loaded) { LoadServiceType(); } Type rs = null; var tempKey = interfaceId; var temp = svcTypeDic.Where(x => x.typeName == tempKey).ToList(); if (temp == null || temp.Count == 0) { return rs; } if (isLocal.HasValue) { if (isLocal.Value) { rs = temp.FirstOrDefault(t => !typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } else { rs = temp.FirstOrDefault(t => typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } } else { rs = temp[0].svcType; } return rs; }
为了性能影响,我们在程序启动的时候可以将当前所有的ApiService类型缓存.
public static void LoadServiceType() { if (_loaded) { return; } lock (_sync) { if (_loaded) { return; } try { svcTypeDic = new List<(string typeName, Type svcType)>(); var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; var dir = new DirectoryInfo(path); var files = dir.GetFiles("XZL*.dll"); foreach (var file in files) { var types = LoadAssemblyFromFile(file); svcTypeDic.AddRange(types); } _loaded = true; } catch { _loaded = false; } } } //加载指定文件中的ApiService实现 private static List<(string typeName, Type svcType)> LoadAssemblyFromFile(FileInfo file) { var lst = new List<(string typeName, Type svcType)>(); if (file.Extension != ".dll" && file.Extension != ".exe") { return lst; } try { var types = Assembly.Load(file.Name.Substring(0, file.Name.Length - 4)) .GetTypes() .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic); foreach (Type type in types) { //客户端代理基类 if (type == typeof(RemoteServiceProxy)) { continue; } if (!typeof(IApiService).IsAssignableFrom(type)) { continue; } //绑定现类 lst.Add((type.FullName, type)); foreach (var interfaceType in type.GetInterfaces()) { if (!typeof(IApiService).IsAssignableFrom(interfaceType)) { continue; } //绑定接口与实际实现类 lst.Add((interfaceType.FullName, type)); } } } catch { } return lst; }
具体api远程服务代理示例
public class UserServiceProxy : RemoteServiceProxy, IUserService { private string serviceId = typeof(IUserService).FullName; public void IncreaseScore(int userId,int score) { return InvokeWithoutReturn(serviceId, nameof(IncreaseScore), userId,score); } public UserInfo GetUserById(int userId) { return Invoke<UserInfo >(serviceId, nameof(GetUserById), userId); } }
结语
经过以上改造后, 我们便可很方便的通过形如 AppRuntime.Instance.GetService<TService>().MethodXX()无感的访问远程服务, 服务是部署在远程还是在本地以dll依赖形式存在,这个便对调用者透明了.无缝的对接上了大家固有习惯.
PS: 但是此番改造后, 遗留下来了另外一个问题: 客户端调用远程服务,需要手动创建一个服务代理( 从 RemoteServiceProxy 继承),虽然每个代理很方便写,只是文中提到的简单两句话,但终究显得繁琐, 是否有一种方式能够根据远程api接口动态的生成这个客户端代理呢? 答案是肯定的,因本文较长了,留在下篇再续
附上动态编译文章链接:www.jb51.net/article/144101.htm
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对易盾网络的支持。
本文共计974个文字,预计阅读时间需要4分钟。
前言:基于.net core的微服务,网上很多介绍都是千篇一律,基于类似webapi的示例,通过http请求形式进行访问,但这并不符合大型企业使用习惯。如何像[GetServiceIOrderService]().SaveOrder(orderInfo)这样的方式,直接调用,提高开发效率?
结果:探讨如何实现类似[GetServiceIOrderService]().SaveOrder(orderInfo)的直接调用方式,提高微服务开发效率。
前言
基于.net core 的微服务,网上很多介绍都是千篇一律基于类似webapi,通过localhost:8801/api/svc" }, { "ServiceId": "XZL.Api.IUserService", "Address": "localhost:8802/api/svc" } ]
AppRuntime.Instance.GetService<TService>()的实现.
private static List<(string typeName, Type svcType)> svcTypeDic; private static ConcurrentDictionary<string, Object> svcInstance = new ConcurrentDictionary<string, object>(); public static TService GetService<TService>() { var serviceId = typeof(TService).FullName; //读取服务配置 var serviceInfo = ServiceConfonfig.Instance.GetServiceInfo(serviceId); if (serviceInfo == null) { return (TService)Activator.CreateInstance(GetSvcType(serviceId)); } else { var rs = GetService<TService>(serviceId + (serviceInfo.IsRemote ? "|Remote" : ""), serviceInfo.IsSingle); if (rs != null && rs is RemoteServiceProxy) { var temp = rs as RemoteServiceProxy; temp.Address = serviceInfo.Address; //指定服务地址 } return rs; } } public static TService GetService<TService>(string interfaceId, bool isSingle) { //服务非单例模式 if (!isSingle) { return (TService)Activator.CreateInstance(GetSvcType(interfaceId)); } object obj = null; if (svcInstance.TryGetValue(interfaceId, out obj) && obj != null) { return (TService)obj; } var svcType = GetSvcType(interfaceId); if (svcType == null) { throw new ICVIPException($"系统中未找到[{interfaceId}]的代理类"); } obj = Activator.CreateInstance(svcType); svcInstance.TryAdd(interfaceId, obj); return (TService)obj; } //获取服务的实现类 public static Type GetSvcType(string interfaceId, bool? isLocal = null) { if (!_loaded) { LoadServiceType(); } Type rs = null; var tempKey = interfaceId; var temp = svcTypeDic.Where(x => x.typeName == tempKey).ToList(); if (temp == null || temp.Count == 0) { return rs; } if (isLocal.HasValue) { if (isLocal.Value) { rs = temp.FirstOrDefault(t => !typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } else { rs = temp.FirstOrDefault(t => typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } } else { rs = temp[0].svcType; } return rs; }
为了性能影响,我们在程序启动的时候可以将当前所有的ApiService类型缓存.
public static void LoadServiceType() { if (_loaded) { return; } lock (_sync) { if (_loaded) { return; } try { svcTypeDic = new List<(string typeName, Type svcType)>(); var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; var dir = new DirectoryInfo(path); var files = dir.GetFiles("XZL*.dll"); foreach (var file in files) { var types = LoadAssemblyFromFile(file); svcTypeDic.AddRange(types); } _loaded = true; } catch { _loaded = false; } } } //加载指定文件中的ApiService实现 private static List<(string typeName, Type svcType)> LoadAssemblyFromFile(FileInfo file) { var lst = new List<(string typeName, Type svcType)>(); if (file.Extension != ".dll" && file.Extension != ".exe") { return lst; } try { var types = Assembly.Load(file.Name.Substring(0, file.Name.Length - 4)) .GetTypes() .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic); foreach (Type type in types) { //客户端代理基类 if (type == typeof(RemoteServiceProxy)) { continue; } if (!typeof(IApiService).IsAssignableFrom(type)) { continue; } //绑定现类 lst.Add((type.FullName, type)); foreach (var interfaceType in type.GetInterfaces()) { if (!typeof(IApiService).IsAssignableFrom(interfaceType)) { continue; } //绑定接口与实际实现类 lst.Add((interfaceType.FullName, type)); } } } catch { } return lst; }
具体api远程服务代理示例
public class UserServiceProxy : RemoteServiceProxy, IUserService { private string serviceId = typeof(IUserService).FullName; public void IncreaseScore(int userId,int score) { return InvokeWithoutReturn(serviceId, nameof(IncreaseScore), userId,score); } public UserInfo GetUserById(int userId) { return Invoke<UserInfo >(serviceId, nameof(GetUserById), userId); } }
结语
经过以上改造后, 我们便可很方便的通过形如 AppRuntime.Instance.GetService<TService>().MethodXX()无感的访问远程服务, 服务是部署在远程还是在本地以dll依赖形式存在,这个便对调用者透明了.无缝的对接上了大家固有习惯.
PS: 但是此番改造后, 遗留下来了另外一个问题: 客户端调用远程服务,需要手动创建一个服务代理( 从 RemoteServiceProxy 继承),虽然每个代理很方便写,只是文中提到的简单两句话,但终究显得繁琐, 是否有一种方式能够根据远程api接口动态的生成这个客户端代理呢? 答案是肯定的,因本文较长了,留在下篇再续
附上动态编译文章链接:www.jb51.net/article/144101.htm
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对易盾网络的支持。

