public static void AddCommandServer(ICommandServer commandServer) { lock (serviceLock) { var exposedTypes = Discovery.GetTypesFromAttribute(typeof(ServiceExposedAttribute)); foreach (var type in exposedTypes) { if (type.IsClass) { if (TypeAnalyzer.GetTypeDetail(type).Interfaces.Any(x => x == typeof(ICommand))) { var interfaceStack = ProviderLayers.GetProviderInterfaceStack(); var hasHandler = Discovery.HasImplementationType(TypeAnalyzer.GetGenericType(typeof(ICommandHandler <>), type), interfaceStack, interfaceStack.Length - 1); if (hasHandler) { if (commandClients.Keys.Contains(type)) { throw new InvalidOperationException($"Cannot create loopback. Command Client already registered for type {type.GetNiceName()}"); } if (!commandServerTypes.Contains(type)) { commandServerTypes.Add(type); } commandServer.RegisterCommandType(type); } } } } commandServer.SetHandler(HandleRemoteCommandDispatchAsync, HandleRemoteCommandDispatchAwaitAsync); commandServers.Add(commandServer); commandServer.Open(); } }
public static void StartServices(string serviceName, ServiceSettings serviceSettings, IServiceCreator serviceCreator, IRelayRegister relayRegister = null) { _ = Log.InfoAsync($"Starting {serviceName}"); lock (serviceLock) { var serverSetting = serviceSettings.Services.FirstOrDefault(x => x.Name == serviceName); if (serverSetting == null) { throw new Exception($"Service {serviceName} not found in {CQRSSettings.SettingsFileName}"); } var serverUrl = Config.GetSetting("urls"); if (String.IsNullOrWhiteSpace(serverUrl)) { serverUrl = Config.GetSetting("ASPNETCORE_URLS"); } if (String.IsNullOrWhiteSpace(serverUrl)) { serverUrl = Config.GetSetting("DOTNET_URLS"); } if (String.IsNullOrWhiteSpace(serverUrl)) { serverUrl = serverSetting.ExternalUrl; } ICommandServer commandServer = null; IEventServer eventServer = null; IQueryServer queryServer = null; var serverTypes = new HashSet <Type>(); foreach (var clientSetting in serviceSettings.Services) { if (clientSetting.Types == null || clientSetting.Types.Length == 0) { continue; } if (clientSetting != serverSetting) { continue; } foreach (var typeName in clientSetting.Types) { var type = Discovery.GetTypeFromName(typeName); if (!type.IsInterface) { throw new Exception($"{type.GetNiceName()} is not an interface"); } var typeDetails = TypeAnalyzer.GetTypeDetail(type); if (!typeDetails.Interfaces.Contains(typeof(IBaseProvider))) { throw new Exception($"{type.GetNiceName()} does not inherit {nameof(IBaseProvider)}"); } var commandTypes = GetCommandTypesFromInterface(type); foreach (var commandType in commandTypes) { serverTypes.Add(commandType); } var eventTypes = GetEventTypesFromInterface(type); foreach (var eventType in eventTypes) { serverTypes.Add(eventType); } if (typeDetails.Attributes.Any(x => x is ServiceExposedAttribute)) { serverTypes.Add(type); } } } foreach (var serviceSetting in serviceSettings.Services) { if (serviceSetting.Types == null || serviceSetting.Types.Length == 0) { continue; } ICommandClient commandClient = null; IEventClient eventClient = null; IQueryClient queryClient = null; foreach (var typeName in serviceSetting.Types) { var type = Discovery.GetTypeFromName(typeName); if (!type.IsInterface) { throw new Exception($"{type.GetNiceName()} is not an interface"); } var typeDetails = TypeAnalyzer.GetTypeDetail(type); if (!typeDetails.Interfaces.Contains(typeof(IBaseProvider))) { throw new Exception($"{type.GetNiceName()} does not inherit {nameof(IBaseProvider)}"); } var commandTypes = GetCommandTypesFromInterface(type); if (commandTypes.Count > 0) { if (serviceSetting == serverSetting) { if (commandServer == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); commandServer = serviceCreator.CreateCommandServer(serverUrl, encryptionKey); commandServer.SetHandler(HandleRemoteCommandDispatchAsync, HandleRemoteCommandDispatchAwaitAsync); if (!commandServers.Contains(commandServer)) { commandServers.Add(commandServer); } } foreach (var commandType in commandTypes) { if (commandClients.Keys.Contains(commandType)) { throw new InvalidOperationException($"Command Client already registered for type {commandType.GetNiceName()}"); } if (commandServerTypes.Contains(commandType)) { throw new InvalidOperationException($"Command Server already registered for type {commandType.GetNiceName()}"); } commandServerTypes.Add(commandType); commandServer.RegisterCommandType(commandType); } } else { if (commandClient == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); commandClient = serviceCreator.CreateCommandClient(relayRegister?.RelayUrl ?? serviceSetting.ExternalUrl, encryptionKey); } var clientCommandTypes = commandTypes.Where(x => !serverTypes.Contains(x)).ToArray(); if (clientCommandTypes.Length > 0) { foreach (var commandType in clientCommandTypes) { if (commandServerTypes.Contains(commandType)) { throw new InvalidOperationException($"Command Server already registered for type {commandType.GetNiceName()}"); } if (commandClients.Keys.Contains(commandType)) { throw new InvalidOperationException($"Command Client already registered for type {commandType.GetNiceName()}"); } commandClients.TryAdd(commandType, commandClient); } } else { if (commandClient is IDisposable disposable) { disposable.Dispose(); } } } } var eventTypes = GetEventTypesFromInterface(type); if (eventTypes.Count > 0) { if (serviceSetting == serverSetting) { if (eventServer == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); eventServer = serviceCreator.CreateEventServer(serverUrl, encryptionKey); eventServer.SetHandler(HandleRemoteEventDispatchAsync); if (!eventServers.Contains(eventServer)) { eventServers.Add(eventServer); } } foreach (var eventType in eventTypes) { if (eventClients.Keys.Contains(eventType)) { throw new InvalidOperationException($"Event Client already registered for type {eventType.GetNiceName()}"); } if (eventServerTypes.Contains(eventType)) { throw new InvalidOperationException($"Event Server already registered for type {eventType.GetNiceName()}"); } eventServerTypes.Add(eventType); eventServer.RegisterEventType(eventType); } } else { if (eventClient == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); eventClient = serviceCreator.CreateEventClient(relayRegister?.RelayUrl ?? serviceSetting.ExternalUrl, encryptionKey); } var clientEventTypes = eventTypes.Where(x => !serverTypes.Contains(x)).ToArray(); if (clientEventTypes.Length > 0) { foreach (var eventType in eventTypes) { if (eventServerTypes.Contains(eventType)) { throw new InvalidOperationException($"Event Server already registered for type {eventType.GetNiceName()}"); } if (!eventClients.Keys.Contains(eventType)) { eventClients.TryAdd(eventType, eventClient); } } } else { if (eventClient is IDisposable disposable) { disposable.Dispose(); } } } } if (typeDetails.Attributes.Any(x => x is ServiceExposedAttribute)) { if (serviceSetting == serverSetting) { if (queryServer == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); queryServer = serviceCreator.CreateQueryServer(serverUrl, encryptionKey); queryServer.SetHandler(HandleRemoteQueryCallAsync); if (!queryServers.Contains(queryServer)) { queryServers.Add(queryServer); } } if (queryClients.Keys.Contains(type)) { throw new InvalidOperationException($"Query Client already registered for type {type.GetNiceName()}"); } if (queryServerTypes.Contains(type)) { throw new InvalidOperationException($"Query Server already registered for type {type.GetNiceName()}"); } queryServerTypes.Add(type); queryServer.RegisterInterfaceType(type); } else { if (queryClient == null) { var encryptionKey = String.IsNullOrWhiteSpace(serviceSetting.EncryptionKey) ? null : SymmetricEncryptor.GetKey(serviceSetting.EncryptionKey); queryClient = serviceCreator.CreateQueryClient(relayRegister?.RelayUrl ?? serviceSetting.ExternalUrl, encryptionKey); } if (!serverTypes.Contains(type)) { if (queryServerTypes.Contains(type)) { throw new InvalidOperationException($"Query Server already registered for type {type.GetNiceName()}"); } if (commandClients.Keys.Contains(type)) { throw new InvalidOperationException($"Query Client already registered for type {type.GetNiceName()}"); } queryClients.TryAdd(type, queryClient); } else { if (queryClient is IDisposable disposable) { disposable.Dispose(); } } } } } } Dictionary <string, HashSet <string> > relayRegisterTypes = null; if (relayRegister != null) { relayRegisterTypes = new Dictionary <string, HashSet <string> >(); } if (commandServer != null) { commandServer.Open(); if (relayRegister != null) { var commandTypes = commandServer.GetCommandTypes().Select(x => x.GetNiceName()).ToArray(); if (!relayRegisterTypes.TryGetValue(commandServer.ConnectionString, out HashSet <string> relayTypes)) { relayTypes = new HashSet <string>(); relayRegisterTypes.Add(commandServer.ConnectionString, relayTypes); } foreach (var type in commandTypes) { relayTypes.Add(type); } } } if (eventServer != null) { eventServer.Open(); if (relayRegister != null) { var eventTypes = eventServer.GetEventTypes().Select(x => x.GetNiceName()).ToArray(); if (!relayRegisterTypes.TryGetValue(eventServer.ConnectionString, out HashSet <string> relayTypes)) { relayTypes = new HashSet <string>(); relayRegisterTypes.Add(eventServer.ConnectionString, relayTypes); } foreach (var type in eventTypes) { relayTypes.Add(type); } } } if (queryServer != null) { queryServer.Open(); if (relayRegister != null) { var queryTypes = queryServer.GetInterfaceTypes().Select(x => x.GetNiceName()).ToArray(); if (!relayRegisterTypes.TryGetValue(queryServer.ConnectionString, out HashSet <string> relayTypes)) { relayTypes = new HashSet <string>(); relayRegisterTypes.Add(queryServer.ConnectionString, relayTypes); } foreach (var type in queryTypes) { relayTypes.Add(type); } } } if (relayRegister != null) { foreach (var group in relayRegisterTypes) { relayRegister.Register(group.Key, group.Value.ToArray()); } } if (serverSetting.InstantiateTypes != null && serverSetting.InstantiateTypes.Length > 0) { foreach (var instantiation in serverSetting.InstantiateTypes) { try { var type = Discovery.GetTypeFromName(instantiation); var instance = Activator.CreateInstance(type); instanciations.Add(instance); } catch (Exception ex) { _ = Log.ErrorAsync($"Failed to instantiate {instantiation}", ex); } } } } }