【问题标题】: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()