/// <summary> /// Registers a workflow implementation with temporal-proxy. /// </summary> /// <param name="workflowType">The workflow implementation type.</param> /// <exception cref="RegistrationException">Thrown when there's a problem with the registration.</exception> private async Task RegisterWorkflowImplementationAsync(Type workflowType) { await SyncContext.Clear; TemporalHelper.ValidateWorkflowImplementation(workflowType); var methodMap = WorkflowMethodMap.Create(workflowType); // We need to register each workflow method that implements a workflow interface method // with the same signature that that was tagged by [WorkflowMethod]. // // First, we'll create a dictionary that maps method signatures from any inherited // interfaces that are tagged by [WorkflowMethod] to the attribute. var methodSignatureToAttribute = new Dictionary <string, WorkflowMethodAttribute>(); foreach (var interfaceType in workflowType.GetInterfaces()) { foreach (var method in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { var workflowMethodAttribute = method.GetCustomAttribute <WorkflowMethodAttribute>(); if (workflowMethodAttribute == null) { continue; } var signature = method.ToString(); if (methodSignatureToAttribute.ContainsKey(signature)) { throw new NotSupportedException($"Workflow type [{workflowType.FullName}] cannot implement the [{signature}] method from two different interfaces."); } methodSignatureToAttribute.Add(signature, workflowMethodAttribute); } } // Next, we need to register the workflow methods that implement the // workflow interface. foreach (var method in workflowType.GetMethods()) { if (!methodSignatureToAttribute.TryGetValue(method.ToString(), out var workflowMethodAttribute)) { continue; } var workflowTypeName = TemporalHelper.GetWorkflowTypeName(workflowType, workflowMethodAttribute); lock (nameToWorkflowRegistration) { if (nameToWorkflowRegistration.TryGetValue(workflowTypeName, out var existingRegistration)) { if (!object.ReferenceEquals(existingRegistration.WorkflowType, workflowType)) { throw new InvalidOperationException($"Conflicting workflow interface registration: Workflow interface [{workflowType.FullName}] is already registered for workflow type name [{workflowTypeName}]."); } } else { nameToWorkflowRegistration[workflowTypeName] = new WorkflowRegistration() { WorkflowType = workflowType, WorkflowMethod = method, WorkflowMethodParameterTypes = method.GetParameterTypes(), MethodMap = methodMap }; } } var reply = (WorkflowRegisterReply)await Client.CallProxyAsync( new WorkflowRegisterRequest() { WorkerId = WorkerId, Name = workflowTypeName, }); reply.ThrowOnError(); } }