C# 修改工作流时,SourceLocationProvider.CollectMapping不会更新

C# 修改工作流时,SourceLocationProvider.CollectMapping不会更新,c#,.net,workflow-foundation-4,workflow-foundation,C#,.net,Workflow Foundation 4,Workflow Foundation,我正在为重新注册的工作流设计器实现VisualTracking。如果文件是新加载到WorkflowDesigner中的,则可视跟踪工作正常,并且从SourceLocationProvider.CollectMapping生成的映射工作成功。但是,如果对工作流进行了修改并重新保存,则SourceLocationProvider仅从原始xaml映射 有没有办法强制SourceLocationProvider在引擎盖下使用的AttachedProperties进行更新 如果试图使用WorkflowDe

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

有没有办法强制SourceLocationProvider在引擎盖下使用的AttachedProperties进行更新


如果试图使用
WorkflowDesigner.Load(..)
则必须创建一个全新的WorkflowDesigner对象,因为WorkflowDesigner只能加载一次文件。如果可能,我希望避免此操作,因为它会丢失任何已设置的调试数据。

对不起,我自己没有尝试过此操作,但是您可以从设计器的ModelChanged事件调用SourceLocationProvider.CollectMapping(…)吗?

对不起,我自己没有尝试过此操作,但是您可以调用SourceLocationProvider.CollectMapping(…)从设计器的ModelChanged事件?

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

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);
}
专用静态字典CreateSourceLocationMapping(
IDesignerDebugView调试视图,
模型服务(模型服务)
{
var nonPublicInstance=BindingFlags.Instance | BindingFlags.NonPublic;
var debuggerServiceType=typeof(DebuggerService);
var ensureMappingMethodName=“ensureResourceLocationUpdate”;
var mappingFieldName=“instanceToSourceLocationMapping”;
var ensureMappingMethod=debuggerServiceType.GetMethod(ensureMappingMethodName,非发布状态);
var mappingField=debuggerServiceType.GetField(mappingFieldName,nonPublicInstance);
如果(ensureMappingMethod==null)
抛出新的MissingMethodException(debuggerServiceType.FullName,ensureMappingMethodName);
if(mappingField==null)
抛出新的MissingFieldException(debuggerServiceType.FullName,mappingFieldName);
var rootActivity=modelService.Root.GetCurrentValue()作为活动;
if(rootActivity!=null)
WorkflowInspectionServices.CacheMetadata(rootActivity);
ensureMappingMethod.Invoke(debugView,新对象[0]);
var-mapping=(Dictionary)mappingField.GetValue(debugView);
返回(从映射中的对)
让activity=pair.Key作为activity
何处活动!=null
选择新{activity.Id,pair.Value})
.ToDictionary(p=>p.Id,p=>p.Value);
}

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

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);
}
专用静态字典CreateSourceLocationMapping(
IDesignerDebugView调试视图,
模型服务(模型服务)
{
var nonPublicInstance=BindingFlags.Instance | BindingFlags.NonPublic;
var debuggerServiceType=typeof(DebuggerService);
var ensureMappingMethodName=“ensureResourceLocationUpdate”;
var mappingFieldName=“instanceToSourceLocationMapping”;
var ensureMappingMethod=debuggerServiceType.GetMethod(ensureMappingMethodName,非发布状态);
var mappingField=debuggerServiceType.GetField(mappingFieldName,nonPublicInstance);
如果(ensureMappingMethod==null)
抛出新的MissingMethodException(debuggerServiceType.FullName,ensureMappingMethodName);
if(mappingField==null)
抛出新的MissingFieldException(debuggerServiceType.FullName,mappingFieldName);
var rootActivity=modelService.Root.GetCurrentValue()作为活动;
if(rootActivity!=null)
WorkflowInspectionServices.CacheMetadata(rootActivity);
ensureMappingMethod.Invoke(debugView,新对象[0]);
var-mapping=(Dictionary)mappingField.GetValue(debugView);
返回(从映射中的对)
让activity=pair.Key作为activity
何处活动!=null
选择新{activity.Id,pair.Value})
.ToDictionary(p=>p.Id,p=>p.Value);
}

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

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;
   }
private Dictionary updateSourceLocationMappingDebuggerService()
{    
Dictionary sourceLocationMapping=新字典();
Dictionary designerSourceLocationMapping=新字典();
MemoryStream ms=新的MemoryStream(Encoding.Default.GetBytes(this.WorkflowDesigner.Text));
DynamicActivity activityToRun=ActivityXamlServices.Load(ms)作为DynamicActivity;
WorkflowInspectionServices.CacheMetadata(activityToRun);
活动documentRootElement=GetRootWorkflowElement(rootInstance);
Activity rootActivity=GetRootRuntimeWorkflowElement(this.workflowToRun);
var fileName=this.WorkflowDesigner.Context.Items.GetValue().LoadedFile;
CollectMapping(rootActivity、documentRootElement、sourceLocationMapping、文件名);
CollectMapping(documentRootElement、documentRootElement、designerSourceLocationMapping、文件名);
if(this.debuggerService!=null)
{
((DebuggerService)this.DebuggerService).UpdateSourceLocations(designerSourceLocationMapping);
}
if(designerSourceLocationMapping.Count!=sourceLocationMapping.Count)
{
foreach(designerSourceLocationMapping中的变量项)
{
如果(!sourceLocationMapping.ContainsValue(item.Value))
添加(item.Key、item.Value);
}
}
this.designerSourceLocationMapping=designerSourceLocationMapping;
返回sourceLocationMapping;
}
我在这里再次更新sourceLocationMapping a