【问题标题】:SourceLocationProvider.CollectMapping does not update when workflow modified修改工作流时 SourceLocationProvider.CollectMapping 不更新
【发布时间】:2012-10-16 00:10:41
【问题描述】:

我正在为重新托管的工作流设计器实施 VisualTracking。如果文件是新加载到 WorkflowDesigner 中,则视觉跟踪工作正常,从SourceLocationProvider.CollectMapping 生成的映射成功工作。但是,如果对工作流进行了修改并重新保存,则 SourceLocationProvider 仅映射来自原始 xaml。

有没有办法强制 SourceLocationProvider 在后台使用的 AttachedProperties 进行更新?

如果有人尝试使用WorkflowDesigner.Load(..),则会创建一个全新的 WorkflowDesigner 对象,因为 WorkflowDesigner 只能加载一次文件。如果可能的话,我想避免这种情况,因为它会丢失任何已设置的调试数据。

【问题讨论】:

    标签: c# .net workflow-foundation-4 workflow-foundation


    【解决方案1】:

    使用反射,可以直接从DebuggerService 本身获取所需信息。以下解决方案对我有用,并在更新工作流程后继续工作:

    private static Dictionary<string, SourceLocation> CreateSourceLocationMapping(
        IDesignerDebugView debugView,
        ModelService modelService)
    {
        var nonPublicInstance = BindingFlags.Instance | BindingFlags.NonPublic;
        var debuggerServiceType = typeof(DebuggerService);
        var ensureMappingMethodName = "EnsureSourceLocationUpdated";
        var mappingFieldName = "instanceToSourceLocationMapping";
        var ensureMappingMethod = debuggerServiceType.GetMethod(ensureMappingMethodName, nonPublicInstance);
        var mappingField = debuggerServiceType.GetField(mappingFieldName, nonPublicInstance);
    
        if (ensureMappingMethod == null)
            throw new MissingMethodException(debuggerServiceType.FullName, ensureMappingMethodName);
        if (mappingField == null)
            throw new MissingFieldException(debuggerServiceType.FullName, mappingFieldName);
    
        var rootActivity = modelService.Root.GetCurrentValue() as Activity;
        if (rootActivity != null) 
            WorkflowInspectionServices.CacheMetadata(rootActivity);
    
        ensureMappingMethod.Invoke(debugView, new object[0]);
        var mapping = (Dictionary<object, SourceLocation>) mappingField.GetValue(debugView);
    
        return (from pair in mapping
                let activity = pair.Key as Activity
                where activity != null
                select new {activity.Id, pair.Value})
            .ToDictionary(p => p.Id, p => p.Value);
    }
    

    【讨论】:

      【解决方案2】:

      抱歉,我自己没有尝试过,但是你能从设计器的 ModelChanged 事件中调用 SourceLocationProvider.CollectMapping(...) 吗?

      【讨论】:

        【解决方案3】:

        我知道为时已晚,但可能会对其他人有所帮助。所以她是我的解决方案

        private Dictionary<object, SourceLocation> UpdateSourceLocationMappingInDebuggerService()
            {    
               Dictionary<object, SourceLocation> sourceLocationMapping = new Dictionary<object, SourceLocation>();
               Dictionary<object, SourceLocation> designerSourceLocationMapping = new Dictionary<object, SourceLocation>();
        
               MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(this.WorkflowDesigner.Text));
               DynamicActivity activityToRun = ActivityXamlServices.Load(ms) as DynamicActivity;
        
               WorkflowInspectionServices.CacheMetadata(activityToRun);
               Activity documentRootElement = GetRootWorkflowElement(rootInstance);
               Activity rootActivity = GetRootRuntimeWorkflowElement(this.workflowToRun);
               var fileName = this.WorkflowDesigner.Context.Items.GetValue<WorkflowFileItem>().LoadedFile;
        
               SourceLocationProvider.CollectMapping(rootActivity, documentRootElement, sourceLocationMapping, fileName);
               SourceLocationProvider.CollectMapping(documentRootElement, documentRootElement, designerSourceLocationMapping, fileName);
        
                   if (this.debuggerService != null)
                    {
                        ((DebuggerService)this.debuggerService).UpdateSourceLocations(designerSourceLocationMapping);
                    }
        
                   if (designerSourceLocationMapping.Count != sourceLocationMapping.Count)
                    {
                        foreach (var item in designerSourceLocationMapping)
                        {
                            if (!sourceLocationMapping.ContainsValue(item.Value))
                                sourceLocationMapping.Add(item.Key, item.Value);
                        }
                    }
        
               this.designerSourceLocationMapping = designerSourceLocationMapping;
               return sourceLocationMapping;
           }
        

        这里我在更新 sourceLocationMapping 之后再次

        ((DebuggerService)this.debuggerService).UpdateSourceLocations()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-24
          • 1970-01-01
          • 1970-01-01
          • 2021-08-12
          相关资源
          最近更新 更多