e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
213 lines
6.9 KiB
C#
213 lines
6.9 KiB
C#
// <copyright>
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace System.Activities.DynamicUpdate
|
|
{
|
|
using System;
|
|
using System.Activities.Validation;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public class UpdateMapMetadata
|
|
{
|
|
private DynamicUpdateMapBuilder.Finalizer finalizer;
|
|
DynamicUpdateMapBuilder.IDefinitionMatcher matcher;
|
|
private Activity targetActivity;
|
|
private bool isDisposed;
|
|
|
|
internal UpdateMapMetadata(DynamicUpdateMapBuilder.Finalizer finalizer,
|
|
DynamicUpdateMapBuilder.IDefinitionMatcher matcher, Activity targetActivity)
|
|
{
|
|
this.finalizer = finalizer;
|
|
this.matcher = matcher;
|
|
this.targetActivity = targetActivity;
|
|
this.isDisposed = false;
|
|
}
|
|
|
|
public void AllowUpdateInsideThisActivity()
|
|
{
|
|
this.ThrowIfDisposed();
|
|
this.finalizer.AllowUpdateInsideCurrentActivity = true;
|
|
this.finalizer.UpdateDisallowedReason = null;
|
|
}
|
|
|
|
public void DisallowUpdateInsideThisActivity(string reason)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
this.finalizer.AllowUpdateInsideCurrentActivity = false;
|
|
this.finalizer.UpdateDisallowedReason = reason;
|
|
}
|
|
|
|
public void AddMatch(Activity updatedChild, Activity originalChild)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
|
|
if (updatedChild != null && originalChild != null)
|
|
{
|
|
this.matcher.AddMatch(updatedChild, originalChild, this.targetActivity);
|
|
}
|
|
}
|
|
|
|
public void AddMatch(Variable updatedVariable, Variable originalVariable)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
|
|
if (updatedVariable != null && originalVariable != null)
|
|
{
|
|
this.matcher.AddMatch(updatedVariable, originalVariable, this.targetActivity);
|
|
}
|
|
}
|
|
|
|
public Activity GetMatch(Activity updatedChild)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
|
|
if (updatedChild != null)
|
|
{
|
|
Activity result = this.matcher.GetMatch(updatedChild);
|
|
if (updatedChild.MemberOf == this.targetActivity.MemberOf)
|
|
{
|
|
return result;
|
|
}
|
|
else if (result != null)
|
|
{
|
|
// GetMatch checks that the activities have the same relationship to declaring parent.
|
|
// But for referenced children, we also need to check whether they have the same relationship
|
|
// to referencing parent.
|
|
// In case of multiple references from the same parent, we'll compare the first one we find.
|
|
bool updatedIsImport;
|
|
bool updatedIsReferenced = IsChild(this.TargetActivity, updatedChild, out updatedIsImport);
|
|
bool updatedIsDelegate = updatedChild.HandlerOf != null;
|
|
|
|
bool originalIsImport;
|
|
bool originalIsReferenced = IsChild(GetMatch(this.TargetActivity), result, out originalIsImport);
|
|
bool originalIsDelegate = result.HandlerOf != null;
|
|
|
|
if (updatedIsReferenced && originalIsReferenced && updatedIsImport == originalIsImport && updatedIsDelegate == originalIsDelegate)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public Variable GetMatch(Variable updatedVariable)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
|
|
if (updatedVariable != null && updatedVariable.Owner == this.TargetActivity)
|
|
{
|
|
Variable result = this.matcher.GetMatch(updatedVariable);
|
|
return result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public bool IsReferenceToImportedChild(Activity childActivity)
|
|
{
|
|
this.ThrowIfDisposed();
|
|
|
|
if (childActivity == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Activity parent = (childActivity.RootActivity == this.TargetActivity.RootActivity) ? this.TargetActivity : GetMatch(this.TargetActivity);
|
|
return IsReferenceToImportedChild(parent, childActivity);
|
|
}
|
|
|
|
internal bool IsUpdateExplicitlyAllowedOrDisallowed
|
|
{
|
|
get
|
|
{
|
|
return this.finalizer.AllowUpdateInsideCurrentActivity.HasValue;
|
|
}
|
|
}
|
|
|
|
internal void Dispose()
|
|
{
|
|
this.isDisposed = true;
|
|
}
|
|
|
|
internal bool AreMatch(Activity updatedActivity, Activity originalActivity)
|
|
{
|
|
return this.matcher.GetMatch(updatedActivity) == originalActivity;
|
|
}
|
|
|
|
internal bool AreMatch(ActivityDelegate updatedDelegate, ActivityDelegate originalDelegate)
|
|
{
|
|
if (updatedDelegate.Handler != null && originalDelegate.Handler != null)
|
|
{
|
|
return this.matcher.GetMatch(updatedDelegate.Handler) == originalDelegate.Handler;
|
|
}
|
|
else
|
|
{
|
|
return updatedDelegate.Handler == null && originalDelegate.Handler == null;
|
|
}
|
|
}
|
|
|
|
internal DynamicUpdateMapBuilder.Finalizer Finalizer
|
|
{
|
|
get
|
|
{
|
|
return this.finalizer;
|
|
}
|
|
}
|
|
|
|
internal Activity TargetActivity
|
|
{
|
|
get
|
|
{
|
|
return this.targetActivity;
|
|
}
|
|
}
|
|
|
|
internal void ThrowIfDisposed()
|
|
{
|
|
if (this.isDisposed)
|
|
{
|
|
throw FxTrace.Exception.AsError(new ObjectDisposedException(ToString()));
|
|
}
|
|
}
|
|
|
|
internal static bool IsChild(Activity parent, Activity child, out bool isImport)
|
|
{
|
|
if (child.HandlerOf == null)
|
|
{
|
|
isImport = parent.ImportedChildren.Contains(child);
|
|
return isImport || parent.Children.Contains(child);
|
|
}
|
|
else
|
|
{
|
|
isImport = parent.ImportedDelegates.Contains(child.HandlerOf);
|
|
return isImport || parent.Delegates.Contains(child.HandlerOf);
|
|
}
|
|
}
|
|
|
|
static bool IsReferenceToImportedChild(Activity parent, Activity child)
|
|
{
|
|
if (child != null && child.MemberOf != parent.MemberOf)
|
|
{
|
|
IdSpace idSpace = parent.MemberOf.Parent;
|
|
while (idSpace != null)
|
|
{
|
|
if (idSpace == child.MemberOf)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
idSpace = idSpace.Parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|