//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 // CSDN博客:https://blog.csdn.net/qq_40374647 // 哔哩哔哩视频:https://space.bilibili.com/94253567 // Gitee源代码仓库:https://gitee.com/RRQM_Home // Github源代码仓库:https://github.com/RRQM // API首页:https://www.yuque.com/rrqm/touchsocket/index // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Reflection; using TouchSocket.Core; using TouchSocket.Http; using TouchSocket.Sockets; namespace TouchSocket.Rpc { /// /// Rpc仓库 /// public class RpcStore : DisposableObject, IEnumerable { /// /// 命名空间 /// public const string Namespace = "namespace"; /// /// 代理键 /// public const string ProxyKey = "proxy"; private static readonly ConcurrentDictionary m_proxyAttributeMap = new ConcurrentDictionary(); private readonly ConcurrentDictionary m_parsers = new ConcurrentDictionary(); private readonly ConcurrentDictionary> m_serverTypes = new ConcurrentDictionary>(); private string m_proxyUrl = "/proxy"; private HttpService m_service; static RpcStore() { SearchAttribute(); } /// /// 实例化一个Rpc仓库。 /// 需要指定容器。一般和对应的服务器、客户端共用一个容器比较好。 /// 如果,仅仅是只有一个解析器的话,可以考虑从配置中,调用 /// public RpcStore(IContainer container) { Container = container ?? throw new ArgumentNullException(nameof(container)); Container.RegisterSingleton(this); if (!container.IsRegistered(typeof(IRpcServerFactory))) { Container.RegisterSingleton(); } SearchAttribute(); } /// /// 代理属性映射。 /// public static ConcurrentDictionary ProxyAttributeMap => m_proxyAttributeMap; /// /// 内置IOC容器 /// public IContainer Container { get; private set; } /// /// 解析器集合。 /// 如果想快速获得对象,请使用,一般key为对象类型名称,或自定义的。 /// public IRpcParser[] RpcParsers => m_parsers.Values.ToArray(); /// /// 请求代理。 /// public Func OnRequestProxy { get; set; } /// /// 代理路径。默认为“/proxy”。 /// 必须以“/”开头 /// public string ProxyUrl { get => m_proxyUrl; set { if (string.IsNullOrEmpty(value)) { value = "/"; } m_proxyUrl = value; } } /// /// 服务类型 /// public Type[] ServerTypes => m_serverTypes.Keys.ToArray(); /// /// 获取IRpcParser /// /// /// public IRpcParser this[string key] => m_parsers[key]; /// /// 从远程获取代理 /// /// /// public static string GetProxyInfo(string url) { string result = Get(url); if (string.IsNullOrEmpty(result)) { throw new Exception("未知错误"); } return result; } /// /// 添加Rpc解析器 /// /// 名称 /// 解析器实例 /// 是否应用已注册服务 public void AddRpcParser(string key, IRpcParser parser, bool applyServer = true) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } if (!m_parsers.TryAdd(key, parser)) { throw new Exception("相同键值得解析器已经存在。"); } parser.SetRpcStore(this); if (applyServer) { foreach (var item in m_serverTypes) { parser.OnRegisterServer(item.Value.ToArray()); } } } /// /// 获取服务类型对应的服务方法。 /// /// /// public MethodInstance[] GetServerMethodInstances(Type serverType) { return m_serverTypes[serverType].ToArray(); } /// /// 执行Rpc /// /// /// /// /// public InvokeResult Execute(IRpcServer rpcServer, object[] ps, ICallContext callContext) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } InvokeResult invokeResult = new InvokeResult(); try { if (callContext.MethodInstance.Filters != null) { for (int i = 0; i < callContext.MethodInstance.Filters.Length; i++) { callContext.MethodInstance.Filters[i].Executing(callContext,ps, ref invokeResult); callContext.MethodInstance.Filters[i].ExecutingAsync(callContext, ps, ref invokeResult); } } if (invokeResult.Status != InvokeStatus.Ready) { return invokeResult; } if (callContext.MethodInstance.HasReturn) { invokeResult.Result = callContext.MethodInstance.Invoke(rpcServer, ps); } else { callContext.MethodInstance.Invoke(rpcServer, ps); } invokeResult.Status = InvokeStatus.Success; if (callContext.MethodInstance.Filters != null) { for (int i = 0; i < callContext.MethodInstance.Filters.Length; i++) { callContext.MethodInstance.Filters[i].Executed(callContext, ps, ref invokeResult); callContext.MethodInstance.Filters[i].ExecutedAsync(callContext, ps, ref invokeResult); } } } catch (TargetInvocationException ex) { invokeResult.Status = InvokeStatus.InvocationException; if (ex.InnerException != null) { invokeResult.Message = "函数内部发生异常,信息:" + ex.InnerException.Message; } else { invokeResult.Message = "函数内部发生异常,信息:未知"; } if (callContext.MethodInstance.Filters != null) { for (int i = 0; i < callContext.MethodInstance.Filters.Length; i++) { callContext.MethodInstance.Filters[i].ExecutException(callContext, ps, ref invokeResult, ex); callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, ref invokeResult, ex); } } } catch (Exception ex) { invokeResult.Status = InvokeStatus.Exception; invokeResult.Message = ex.Message; if (callContext.MethodInstance.Filters != null) { for (int i = 0; i < callContext.MethodInstance.Filters.Length; i++) { callContext.MethodInstance.Filters[i].ExecutException(callContext, ps, ref invokeResult, ex); callContext.MethodInstance.Filters[i].ExecutExceptionAsync(callContext, ps, ref invokeResult, ex); } } } return invokeResult; } /// /// 获取所有已注册的函数。 /// public MethodInstance[] GetAllMethods() { List methods = new List(); foreach (var item in m_serverTypes.Values) { methods.AddRange(item); } return methods.ToArray(); } IEnumerator IEnumerable.GetEnumerator() { return m_parsers.Values.GetEnumerator(); } /// /// 返回枚举对象 /// /// IEnumerator IEnumerable.GetEnumerator() { return m_parsers.Values.GetEnumerator(); } /// /// 本地获取代理 /// /// /// /// public string GetProxyCodes(string @namespace, Type[] attrbuteTypes) { var cellCodes = GetProxyInfo(attrbuteTypes == null ? ProxyAttributeMap.Values.ToArray() : attrbuteTypes); return CodeGenerator.ConvertToCode(@namespace, cellCodes); } /// /// 本地获取代理 /// /// /// public string GetProxyCodes(string @namespace) { return GetProxyCodes(@namespace, null); } /// /// 从本地获取代理 /// /// public ServerCellCode[] GetProxyInfo() { return GetProxyInfo(ProxyAttributeMap.Values.ToArray()); } /// /// 从本地获取代理 /// /// /// public ServerCellCode[] GetProxyInfo(Type[] attrbuteType) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } List codes = new List(); foreach (var attrbute in attrbuteType) { foreach (var item in m_serverTypes.Keys) { ServerCellCode serverCellCode = CodeGenerator.Generator(item, attrbute); codes.Add(serverCellCode); } } return codes.ToArray(); } /// /// 移除Rpc解析器 /// /// /// /// public bool RemoveRpcParser(string parserName, out IRpcParser parser) { return m_parsers.TryRemove(parserName, out parser); } /// /// 移除Rpc解析器 /// /// /// public bool RemoveRpcParser(string parserName) { return RemoveRpcParser(parserName, out _); } /// /// 分享代理。 /// /// public void ShareProxy(IPHost iPHost) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } if (m_service != null) { return; } m_service = new HttpService(); m_service.Setup(new TouchSocketConfig() .SetListenIPHosts(new IPHost[] { iPHost })) .Start(); m_service.AddPlugin(new InternalPlugin(this)); } /// /// 关闭分享中心 /// public void StopShareProxy() { m_service.SafeDispose(); } /// /// 获取IRpcParser /// /// /// /// public bool TryGetRpcParser(string key, out IRpcParser parser) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } return m_parsers.TryGetValue(key, out parser); } /// /// 移除注册服务 /// /// /// public int UnregisterServer(IRpcServer provider) { return UnregisterServer(provider.GetType()); } /// /// 移除注册服务 /// /// /// public int UnregisterServer(Type providerType) { if (DisposedValue) { throw new ObjectDisposedException(GetType().FullName); } if (!typeof(IRpcServer).IsAssignableFrom(providerType)) { throw new RpcException("类型不相符"); } if (RemoveServer(providerType, out MethodInstance[] instances)) { foreach (var parser in this) { parser.OnUnregisterServer(instances); } return instances.Length; } return 0; } /// /// 移除注册服务 /// /// /// public int UnregisterServer() where T : IRpcServer { return UnregisterServer(typeof(T)); } internal bool TryRemove(string key, out IRpcParser parser) { return m_parsers.TryRemove(key, out parser); } /// /// /// /// protected override void Dispose(bool disposing) { if (!DisposedValue) { StopShareProxy(); foreach (var item in this) { item.SafeDispose(); } } base.Dispose(disposing); } private static string Get(string url) { string result = null; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); //添加参数 HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Stream stream = resp.GetResponseStream(); try { //获取内容 using (StreamReader reader = new StreamReader(stream)) { result = reader.ReadToEnd(); } } finally { resp.SafeDispose(); stream.Close(); } return result; } private static void SearchAttribute() { List types = new List(); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { try { Type[] t1 = assembly.GetTypes().Where(p => typeof(RpcAttribute).IsAssignableFrom(p) && !p.IsAbstract).ToArray(); types.AddRange(t1); } catch { } } foreach (Type type in types) { ProxyAttributeMap.TryAdd(type.Name.Replace("Attribute", string.Empty).ToLower(), type); } } private bool RemoveServer(Type type, out MethodInstance[] methodInstances) { foreach (var newType in m_serverTypes.Keys) { if (newType.FullName == type.FullName) { m_serverTypes.TryRemove(newType, out var list); methodInstances = list.ToArray(); return true; } } methodInstances = null; return false; } #region 注册 /// /// 注册为单例服务 /// /// /// /// public void RegisterServer(Type serverFromType, IRpcServer rpcServer) { if (!typeof(IRpcServer).IsAssignableFrom(serverFromType)) { throw new RpcException($"注册类型必须与{nameof(IRpcServer)}有继承关系"); } if (!serverFromType.IsAssignableFrom(rpcServer.GetType())) { throw new RpcException("实例类型必须与注册类型有继承关系。"); } foreach (var item in m_serverTypes.Keys) { if (item.FullName == serverFromType.FullName) { throw new RpcException($"名为{serverFromType.FullName}的类型已注册。"); } } MethodInstance[] methodInstances = CodeGenerator.GetMethodInstances(serverFromType, rpcServer.GetType()); foreach (var item in methodInstances) { item.IsSingleton = true; //item.ServerFactory = new RpcServerFactory(this.Container); item.ServerFactory = Container.Resolve() ?? throw new ArgumentNullException($"{nameof(IRpcServerFactory)}"); } m_serverTypes.TryAdd(serverFromType, new List(methodInstances)); Container.RegisterSingleton(serverFromType, rpcServer); foreach (var parser in this) { parser.OnRegisterServer(methodInstances); } } /// /// 注册服务 /// /// /// /// public void RegisterServer(Type serverFromType, Type serverToType) { if (!typeof(IRpcServer).IsAssignableFrom(serverFromType)) { throw new RpcException($"注册类型必须与{nameof(IRpcServer)}有继承关系"); } if (!serverFromType.IsAssignableFrom(serverToType)) { throw new RpcException("实例类型必须与注册类型有继承关系。"); } foreach (var item in m_serverTypes.Keys) { if (item.FullName == serverFromType.FullName) { throw new RpcException($"名为{serverFromType.FullName}的类型已注册。"); } } bool singleton; if (typeof(ITransientRpcServer).IsAssignableFrom(serverFromType)) { singleton = false; Container.RegisterTransient(serverFromType, serverToType); } else { singleton = true; Container.RegisterSingleton(serverFromType, serverToType); } MethodInstance[] methodInstances = CodeGenerator.GetMethodInstances(serverFromType, serverToType); foreach (var item in methodInstances) { item.IsSingleton = singleton; //item.ServerFactory = new RpcServerFactory(this.Container); item.ServerFactory = Container.Resolve() ?? throw new ArgumentNullException($"{nameof(IRpcServerFactory)}"); } m_serverTypes.TryAdd(serverFromType, new List(methodInstances)); foreach (var parser in this) { parser.OnRegisterServer(methodInstances); } } #endregion 注册 } internal class InternalPlugin : HttpPluginBase { private readonly RpcStore m_rpcStore; public InternalPlugin(RpcStore rpcCerter) { m_rpcStore = rpcCerter; } protected override void OnGet(ITcpClientBase client, HttpContextEventArgs e) { if (e.Context.Request.UrlEquals(m_rpcStore.ProxyUrl)) { bool? b = m_rpcStore.OnRequestProxy?.Invoke(e.Context.Request); if (b == false) { using (ByteBlock byteBlock = new ByteBlock()) { e.Context.Response .FromText("拒绝响应内容") .SetStatus("403", "Forbidden") .Build(byteBlock); client.DefaultSend(byteBlock); } return; } string value = e.Context.Request.Query[RpcStore.ProxyKey]; List types = new List(); if (value.Equals("all", StringComparison.CurrentCultureIgnoreCase)) { types = RpcStore.ProxyAttributeMap.Values.ToList(); } else { string[] vs = value.Split(','); foreach (var item in vs) { if (RpcStore.ProxyAttributeMap.TryGetValue(item, out Type type)) { types.Add(type); } } } string names = e.Context.Request.Query[RpcStore.Namespace]; names = string.IsNullOrEmpty(names) ? "RRQMProxy" : names; string code = CodeGenerator.ConvertToCode(names, m_rpcStore.GetProxyInfo(types.ToArray())); using (ByteBlock byteBlock = new ByteBlock()) { e.Context.Response .SetStatus() .SetContent(code) .SetContentTypeFromFileName($"{names}.cs") .Build(byteBlock); client.DefaultSend(byteBlock); } } base.OnGet(client, e); } } }