private async Task <CsSource> UpdateSubscriptionAsync(CsField subscriptionField, CsClass sourceClass, VsCSharpSource source) { SourceFormatter formatter = new SourceFormatter(); string injectSourceCode = null; var contract = subscriptionField.DataType.GetInterfaceModel(); if (contract == null) { return(null); } CsSource sourceCode = source.SourceCode; try { CsClass currentClass = sourceClass; var events = contract.Events; var subscribePath = ContractHelper.GetSubscribeFilePath(currentClass); if (!subscribePath.hasFile) { var manager = sourceCode.LoadNamespaceManager(sourceClass.Namespace); var parent = await source.GetParentAsync(); if (parent == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } VsDocument generatedDocument = null; string partialClassSource = CSharpSourceGenerationCommon.GeneratePartialClass(currentClass, manager); if (parent.ModelType == VisualStudioModelType.ProjectFolder) { var parentFolder = parent as VsProjectFolder; if (parentFolder == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } generatedDocument = await parentFolder.AddDocumentAsync(Path.GetFileName(subscribePath.filePath), partialClassSource); } else { var parentProject = parent as VsProject; if (parentProject == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } generatedDocument = await parentProject.AddDocumentAsync(subscribePath.filePath, partialClassSource); } sourceCode = await generatedDocument.GetCSharpSourceModelAsync(); sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } else { var parent = await source.GetParentAsync(); VsCSharpSource sourceDocument = null; if (parent.ModelType == VisualStudioModelType.ProjectFolder) { var parentFolder = parent as VsProjectFolder; if (parentFolder == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var children = await parentFolder.GetChildrenAsync(false, true); sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath); } else { var parentProject = parent as VsProject; if (parentProject == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var children = await parentProject.GetChildrenAsync(false, true); sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath);; } if (sourceDocument == null) { throw new CodeFactoryException("Could load the contract document."); } sourceCode = sourceDocument.SourceCode; sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var namespaceManager = sourceCode.LoadNamespaceManager(currentClass.Namespace); foreach (var contractEvent in contract.Events) { var eventHandlerName = CSharpSourceGenerationWPF.GenerateContractEventHandlerMethodName(subscriptionField, contractEvent); if (eventHandlerName == null) { throw new CodeFactoryException($"Could not create the source code for a contract event handler."); } if (currentClass.Methods.Any(m => m.Name == eventHandlerName)) { continue; } var eventHandlerSource = CSharpSourceGenerationWPF.GenerateContractEventHandlerMethod(subscriptionField, contractEvent, namespaceManager); if (eventHandlerSource == null) { throw new CodeFactoryException($"Could not create the source code for the event handler {eventHandlerName}"); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, eventHandlerSource)); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var subscriptionName = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethodName(subscriptionField); var subscriptionMethod = currentClass.Methods.FirstOrDefault(m => m.Name == subscriptionName); if (subscriptionMethod != null) { sourceCode = await subscriptionMethod.DeleteAsync(); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var subscriptionSource = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethod(subscriptionField, contract); if (subscriptionSource == null) { throw new CodeFactoryException("Cannot generate the subscription contract source code."); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, subscriptionSource)); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } var releaseName = CSharpSourceGenerationWPF.GenerateContractReleaseMethodName(subscriptionField); var releaseMethod = currentClass.Methods.FirstOrDefault(m => m.Name == releaseName); if (releaseMethod != null) { sourceCode = await releaseMethod.DeleteAsync(); currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass; if (currentClass == null) { throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription"); } } var releaseSource = CSharpSourceGenerationWPF.GenerateContractReleaseMethod(subscriptionField, contract); if (releaseSource == null) { throw new CodeFactoryException("Cannot generate the release contract source code."); } sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, releaseSource)); } catch (CodeFactoryException) { throw; } catch (Exception unhandledException) { throw new CodeFactoryException("The following unhandledException occured", unhandledException); } return(sourceCode); }