You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,310 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.XamlIntegration
|
||||
{
|
||||
using System;
|
||||
using System.Activities;
|
||||
using System.Activities.Expressions;
|
||||
using System.Activities.Runtime;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[DataContract(Name = XD.CompiledLocation.Name, Namespace = XD.Runtime.Namespace)]
|
||||
internal class CompiledLocation<T> : Location<T>
|
||||
{
|
||||
Func<T> getMethod;
|
||||
Action<T> setMethod;
|
||||
|
||||
int expressionId;
|
||||
|
||||
IList<LocationReference> locationReferences;
|
||||
|
||||
IList<Location> locations;
|
||||
|
||||
ActivityInstance rootInstance;
|
||||
|
||||
Activity compiledRootActivity;
|
||||
byte[] compiledRootActivityQualifiedId;
|
||||
|
||||
Activity expressionActivity;
|
||||
byte[] expressionActivityQualifiedId;
|
||||
|
||||
string expressionText;
|
||||
|
||||
bool forImplementation;
|
||||
|
||||
public CompiledLocation(Func<T> getMethod, Action<T> setMethod, IList<LocationReference> locationReferences, IList<Location> locations, int expressionId, Activity compiledRootActivity, ActivityContext currentActivityContext)
|
||||
{
|
||||
this.getMethod = getMethod;
|
||||
this.setMethod = setMethod;
|
||||
|
||||
this.forImplementation = currentActivityContext.Activity.MemberOf != currentActivityContext.Activity.RootActivity.MemberOf;
|
||||
this.locationReferences = locationReferences;
|
||||
this.locations = locations;
|
||||
this.expressionId = expressionId;
|
||||
|
||||
this.compiledRootActivity = compiledRootActivity;
|
||||
this.expressionActivity = currentActivityContext.Activity;
|
||||
//
|
||||
// Save the root activity instance to get the root activity post persistence
|
||||
// The root will always be alive as long as the location is valid, which is not
|
||||
// true for the activity instance of the expression that is executing
|
||||
this.rootInstance = currentActivityContext.CurrentInstance;
|
||||
while (this.rootInstance.Parent != null)
|
||||
{
|
||||
this.rootInstance = this.rootInstance.Parent;
|
||||
}
|
||||
//
|
||||
// Save the text of the expression for exception message
|
||||
ITextExpression textExpression = currentActivityContext.Activity as ITextExpression;
|
||||
if (textExpression != null)
|
||||
{
|
||||
this.expressionText = textExpression.ExpressionText;
|
||||
}
|
||||
}
|
||||
|
||||
public CompiledLocation(Func<T> getMethod, Action<T> setMethod)
|
||||
{
|
||||
//
|
||||
// This is the constructor that is used to refresh the get/set methods during rehydration
|
||||
// An instance of this class created with the constructor cannot be invoked.
|
||||
this.getMethod = getMethod;
|
||||
this.setMethod = setMethod;
|
||||
}
|
||||
|
||||
public override T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.getMethod == null)
|
||||
{
|
||||
RefreshAccessors();
|
||||
}
|
||||
return getMethod();
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.setMethod == null)
|
||||
{
|
||||
RefreshAccessors();
|
||||
}
|
||||
setMethod(value);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public byte[] CompiledRootActivityQualifiedId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.compiledRootActivityQualifiedId == null)
|
||||
{
|
||||
return this.compiledRootActivity.QualifiedId.AsByteArray();
|
||||
}
|
||||
|
||||
return this.compiledRootActivityQualifiedId;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.compiledRootActivityQualifiedId = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public byte[] ExpressionActivityQualifiedId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.expressionActivityQualifiedId == null)
|
||||
{
|
||||
return this.expressionActivity.QualifiedId.AsByteArray();
|
||||
}
|
||||
|
||||
return this.expressionActivityQualifiedId;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.expressionActivityQualifiedId = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public IList<Tuple<string, Type>> locationReferenceCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.locationReferences == null || this.locationReferences.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Tuple<string, Type>> durableCache = new List<Tuple<string, Type>>(this.locationReferences.Count);
|
||||
|
||||
foreach (LocationReference reference in locationReferences)
|
||||
{
|
||||
durableCache.Add(new Tuple<string, Type>(reference.Name, reference.Type));
|
||||
}
|
||||
|
||||
return durableCache;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null || value.Count == 0)
|
||||
{
|
||||
this.locationReferences = new List<LocationReference>();
|
||||
return;
|
||||
}
|
||||
|
||||
this.locationReferences = new List<LocationReference>(value.Count);
|
||||
foreach (Tuple<string, Type> reference in value)
|
||||
{
|
||||
this.locationReferences.Add(new CompiledLocationReference(reference.Item1, reference.Item2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "expressionId")]
|
||||
internal int SerializedExpressionId
|
||||
{
|
||||
get { return this.expressionId; }
|
||||
set { this.expressionId = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "locations")]
|
||||
internal IList<Location> SerializedLocations
|
||||
{
|
||||
get { return this.locations; }
|
||||
set { this.locations = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "rootInstance")]
|
||||
internal ActivityInstance SerializedRootInstance
|
||||
{
|
||||
get { return this.rootInstance; }
|
||||
set { this.rootInstance = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "expressionText")]
|
||||
internal string SerializedExpressionText
|
||||
{
|
||||
get { return this.expressionText; }
|
||||
set { this.expressionText = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "forImplementation")]
|
||||
internal bool SerializedForImplementation
|
||||
{
|
||||
get { return this.forImplementation; }
|
||||
set { this.forImplementation = value; }
|
||||
}
|
||||
|
||||
void RefreshAccessors()
|
||||
{
|
||||
//
|
||||
// If we've gotten here is means that we have a location that has roundtripped through persistence
|
||||
// CompiledDataContext & ICER don't round trip so we need to get them back from the current tree
|
||||
// and get new pointers to the get/set methods for this expression
|
||||
ICompiledExpressionRoot compiledRoot = GetCompiledExpressionRoot();
|
||||
CompiledLocation<T> tempLocation = (CompiledLocation<T>)compiledRoot.InvokeExpression(this.expressionId, this.locations);
|
||||
this.getMethod = tempLocation.getMethod;
|
||||
this.setMethod = tempLocation.setMethod;
|
||||
}
|
||||
|
||||
ICompiledExpressionRoot GetCompiledExpressionRoot()
|
||||
{
|
||||
if (this.rootInstance != null && this.rootInstance.Activity != null)
|
||||
{
|
||||
ICompiledExpressionRoot compiledExpressionRoot;
|
||||
Activity rootActivity = this.rootInstance.Activity;
|
||||
|
||||
Activity compiledRootActivity = null;
|
||||
Activity expressionActivity = null;
|
||||
|
||||
if (QualifiedId.TryGetElementFromRoot(rootActivity, this.compiledRootActivityQualifiedId, out compiledRootActivity) &&
|
||||
QualifiedId.TryGetElementFromRoot(rootActivity, this.expressionActivityQualifiedId, out expressionActivity))
|
||||
{
|
||||
if (CompiledExpressionInvoker.TryGetCompiledExpressionRoot(expressionActivity, compiledRootActivity, out compiledExpressionRoot))
|
||||
{
|
||||
//
|
||||
// Revalidate to make sure we didn't hit an ID shift
|
||||
if (compiledExpressionRoot.CanExecuteExpression(this.expressionText, true /* this is always a reference */, this.locationReferences, out this.expressionId))
|
||||
{
|
||||
return compiledExpressionRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// We were valid when this location was generated so an ID shift occurred (likely due to a dynamic update)
|
||||
// Need to search all of the ICERs for one that can execute this expression.
|
||||
if (FindCompiledExpressionRoot(rootActivity, out compiledExpressionRoot))
|
||||
{
|
||||
return compiledExpressionRoot;
|
||||
}
|
||||
}
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UnableToLocateCompiledLocationContext(this.expressionText)));
|
||||
}
|
||||
|
||||
bool FindCompiledExpressionRoot(Activity activity, out ICompiledExpressionRoot compiledExpressionRoot)
|
||||
{
|
||||
if (CompiledExpressionInvoker.TryGetCompiledExpressionRoot(activity, this.forImplementation, out compiledExpressionRoot))
|
||||
{
|
||||
if (compiledExpressionRoot.CanExecuteExpression(this.expressionText, true /* this is always a reference */, this.locationReferences, out this.expressionId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Activity containedActivity in WorkflowInspectionServices.GetActivities(activity))
|
||||
{
|
||||
if (FindCompiledExpressionRoot(containedActivity, out compiledExpressionRoot))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
compiledExpressionRoot = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
class CompiledLocationReference : LocationReference
|
||||
{
|
||||
string name;
|
||||
Type type;
|
||||
|
||||
public CompiledLocationReference(string name, Type type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
protected override string NameCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Type TypeCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public override Location GetLocation(ActivityContext context)
|
||||
{
|
||||
//
|
||||
// We should never hit this, these references are strictly for preserving location names/types
|
||||
// through persistence to allow for revalidation on the other side
|
||||
// Actual execution occurs through the locations that were stored separately
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CompiledLocationReferenceGetLocation));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user