e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
663 lines
27 KiB
C#
663 lines
27 KiB
C#
//----------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------
|
|
namespace System.Activities.Statements
|
|
{
|
|
using System.Activities.DynamicUpdate;
|
|
using System.Activities.Validation;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Runtime;
|
|
using System.Runtime.Collections;
|
|
using System.Windows.Markup;
|
|
using System.Linq;
|
|
using System.Activities.Expressions;
|
|
using SA = System.Activities;
|
|
|
|
[ContentProperty("Body")]
|
|
public sealed class CompensableActivity : NativeActivity<CompensationToken>
|
|
{
|
|
static Constraint noCompensableActivityInSecondaryRoot = CompensableActivity.NoCompensableActivityInSecondaryRoot();
|
|
|
|
Collection<Variable> variables;
|
|
|
|
CompensationParticipant compensationParticipant;
|
|
|
|
Variable<long> currentCompensationId;
|
|
Variable<CompensationToken> currentCompensationToken;
|
|
|
|
// This id will be passed to secondary root.
|
|
Variable<long> compensationId;
|
|
|
|
public CompensableActivity()
|
|
: base()
|
|
{
|
|
this.currentCompensationToken = new Variable<CompensationToken>();
|
|
this.currentCompensationId = new Variable<long>();
|
|
this.compensationId = new Variable<long>();
|
|
}
|
|
|
|
public Collection<Variable> Variables
|
|
{
|
|
get
|
|
{
|
|
if (this.variables == null)
|
|
{
|
|
this.variables = new ValidatingCollection<Variable>
|
|
{
|
|
// disallow null values
|
|
OnAddValidationCallback = item =>
|
|
{
|
|
if (item == null)
|
|
{
|
|
throw SA.FxTrace.Exception.ArgumentNull("item");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return this.variables;
|
|
}
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
[DependsOn("Variables")]
|
|
public Activity Body
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
[DependsOn("Body")]
|
|
public Activity CancellationHandler
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
[DependsOn("CancellationHandler")]
|
|
public Activity CompensationHandler
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
[DependsOn("CompensationHandler")]
|
|
public Activity ConfirmationHandler
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
protected override bool CanInduceIdle
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Internal properties.
|
|
CompensationParticipant CompensationParticipant
|
|
{
|
|
get
|
|
{
|
|
if (this.compensationParticipant == null)
|
|
{
|
|
this.compensationParticipant = new CompensationParticipant(this.compensationId);
|
|
|
|
if (CompensationHandler != null)
|
|
{
|
|
this.compensationParticipant.CompensationHandler = CompensationHandler;
|
|
}
|
|
|
|
if (ConfirmationHandler != null)
|
|
{
|
|
this.compensationParticipant.ConfirmationHandler = ConfirmationHandler;
|
|
}
|
|
|
|
if (CancellationHandler != null)
|
|
{
|
|
this.compensationParticipant.CancellationHandler = CancellationHandler;
|
|
}
|
|
}
|
|
|
|
return this.compensationParticipant;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.compensationParticipant = value;
|
|
}
|
|
}
|
|
|
|
protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
|
|
{
|
|
metadata.AllowUpdateInsideThisActivity();
|
|
}
|
|
|
|
protected override void CacheMetadata(NativeActivityMetadata metadata)
|
|
{
|
|
metadata.SetVariablesCollection(this.Variables);
|
|
|
|
metadata.SetImplementationVariablesCollection(
|
|
new Collection<Variable>
|
|
{
|
|
this.currentCompensationId,
|
|
this.currentCompensationToken,
|
|
|
|
// Add the variables which are only used by the secondary root
|
|
this.compensationId
|
|
});
|
|
|
|
if (this.Body != null)
|
|
{
|
|
metadata.SetChildrenCollection(new Collection<Activity> { this.Body });
|
|
}
|
|
|
|
// Declare the handlers as public children.
|
|
if (this.CompensationHandler != null)
|
|
{
|
|
metadata.AddImportedChild(this.CompensationHandler);
|
|
}
|
|
|
|
if (this.ConfirmationHandler != null)
|
|
{
|
|
metadata.AddImportedChild(this.ConfirmationHandler);
|
|
}
|
|
|
|
if (this.CancellationHandler != null)
|
|
{
|
|
metadata.AddImportedChild(this.CancellationHandler);
|
|
}
|
|
|
|
Collection<Activity> implementationChildren = new Collection<Activity>();
|
|
|
|
if (!this.IsSingletonActivityDeclared(CompensationActivityStrings.WorkflowImplicitCompensationBehavior))
|
|
{
|
|
WorkflowCompensationBehavior workflowCompensationBehavior = new WorkflowCompensationBehavior();
|
|
this.DeclareSingletonActivity(CompensationActivityStrings.WorkflowImplicitCompensationBehavior, workflowCompensationBehavior);
|
|
implementationChildren.Add(workflowCompensationBehavior);
|
|
|
|
metadata.AddDefaultExtensionProvider(CreateCompensationExtension);
|
|
}
|
|
|
|
// Clear the cached handler values as workflow definition could be updated.
|
|
CompensationParticipant = null;
|
|
implementationChildren.Add(CompensationParticipant);
|
|
|
|
metadata.SetImplementationChildrenCollection(implementationChildren);
|
|
}
|
|
|
|
CompensationExtension CreateCompensationExtension()
|
|
{
|
|
return new CompensationExtension();
|
|
}
|
|
|
|
internal override IList<Constraint> InternalGetConstraints()
|
|
{
|
|
return new List<Constraint>(1) { noCompensableActivityInSecondaryRoot };
|
|
}
|
|
|
|
static Constraint NoCompensableActivityInSecondaryRoot()
|
|
{
|
|
DelegateInArgument<ValidationContext> validationContext = new DelegateInArgument<ValidationContext> { Name = "validationContext" };
|
|
DelegateInArgument<CompensableActivity> element = new DelegateInArgument<CompensableActivity> { Name = "element" };
|
|
Variable<bool> assertFlag = new Variable<bool> { Name = "assertFlag", Default = true };
|
|
Variable<IEnumerable<Activity>> elements = new Variable<IEnumerable<Activity>>() { Name = "elements" };
|
|
Variable<int> index = new Variable<int>() { Name = "index" };
|
|
|
|
return new Constraint<CompensableActivity>
|
|
{
|
|
Body = new ActivityAction<CompensableActivity, ValidationContext>
|
|
{
|
|
Argument1 = element,
|
|
Argument2 = validationContext,
|
|
Handler = new Sequence
|
|
{
|
|
Variables =
|
|
{
|
|
assertFlag,
|
|
elements,
|
|
index
|
|
},
|
|
Activities =
|
|
{
|
|
new Assign<IEnumerable<Activity>>
|
|
{
|
|
To = elements,
|
|
Value = new GetParentChain
|
|
{
|
|
ValidationContext = validationContext,
|
|
},
|
|
},
|
|
// Need to replace the lambda expression with a CodeActivity for partial trust.
|
|
// new While(env => (assertFlag.Get(env) != false) && index.Get(env) < elements.Get(env).Count())
|
|
new While
|
|
{
|
|
Condition = new WhileExpression
|
|
{
|
|
DisplayName = "env => (assertFlag.Get(env) != false) && index.Get(env) < elements.Get(env).Count())",
|
|
AssertFlag = new InArgument<bool>(assertFlag),
|
|
Index = new InArgument<int>(index),
|
|
Elements = new InArgument<IEnumerable<Activity>>(elements)
|
|
},
|
|
|
|
Body = new Sequence
|
|
{
|
|
Activities =
|
|
{
|
|
// Need to replace the lambda expression with a CodeActivity for partial trust.
|
|
// new If(env => (elements.Get(env).ElementAt(index.Get(env))).GetType() == typeof(CompensationParticipant))
|
|
new If
|
|
{
|
|
Condition = new IfExpression
|
|
{
|
|
DisplayName = "env => (elements.Get(env).ElementAt(index.Get(env))).GetType() == typeof(CompensationParticipant)",
|
|
Elements = new InArgument<IEnumerable<Activity>>(elements),
|
|
Index = new InArgument<int>(index)
|
|
},
|
|
|
|
Then = new Assign<bool>
|
|
{
|
|
To = assertFlag,
|
|
Value = false
|
|
},
|
|
},
|
|
new Assign<int>
|
|
{
|
|
To = index,
|
|
// Need to replace the lambda expression for partial trust. Using Add expression activity instead of a CodeActivity here.
|
|
// Value = new InArgument<int>(env => index.Get(env) + 1)
|
|
Value = new InArgument<int>
|
|
{
|
|
Expression = new Add<int, int, int>
|
|
{
|
|
DisplayName = "(env => index.Get(env) + 1)",
|
|
Left = new VariableValue<int>
|
|
{
|
|
Variable = index
|
|
},
|
|
Right = 1,
|
|
}
|
|
}
|
|
},
|
|
}
|
|
}
|
|
},
|
|
new AssertValidation
|
|
{
|
|
Assertion = new InArgument<bool>(assertFlag),
|
|
Message = new InArgument<string>(SA.SR.NoCAInSecondaryRoot)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
protected override void Execute(NativeActivityContext context)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
if (compensationExtension.IsWorkflowCompensationBehaviorScheduled)
|
|
{
|
|
ScheduleBody(context, compensationExtension);
|
|
}
|
|
else
|
|
{
|
|
compensationExtension.SetupWorkflowCompensationBehavior(context, new BookmarkCallback(OnWorkflowCompensationBehaviorScheduled), GetSingletonActivity(CompensationActivityStrings.WorkflowImplicitCompensationBehavior));
|
|
}
|
|
}
|
|
|
|
protected override void Cancel(NativeActivityContext context)
|
|
{
|
|
context.CancelChildren();
|
|
}
|
|
|
|
void OnWorkflowCompensationBehaviorScheduled(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
ScheduleBody(context, compensationExtension);
|
|
}
|
|
|
|
void ScheduleBody(NativeActivityContext context, CompensationExtension compensationExtension)
|
|
{
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
CompensationToken parentToken = null;
|
|
long parentCompensationId = CompensationToken.RootCompensationId;
|
|
|
|
parentToken = (CompensationToken)context.Properties.Find(CompensationToken.PropertyName);
|
|
|
|
if (parentToken != null)
|
|
{
|
|
if (compensationExtension.Get(parentToken.CompensationId).IsTokenValidInSecondaryRoot)
|
|
{
|
|
throw SA.FxTrace.Exception.AsError(new InvalidOperationException(SA.SR.NoCAInSecondaryRoot));
|
|
}
|
|
|
|
parentCompensationId = parentToken.CompensationId;
|
|
}
|
|
|
|
CompensationTokenData tokenData = new CompensationTokenData(compensationExtension.GetNextId(), parentCompensationId)
|
|
{
|
|
CompensationState = CompensationState.Active,
|
|
DisplayName = this.DisplayName,
|
|
};
|
|
CompensationToken token = new CompensationToken(tokenData);
|
|
|
|
context.Properties.Add(CompensationToken.PropertyName, token);
|
|
|
|
this.currentCompensationId.Set(context, token.CompensationId);
|
|
this.currentCompensationToken.Set(context, token);
|
|
|
|
compensationExtension.Add(token.CompensationId, tokenData);
|
|
|
|
if (TD.CompensationStateIsEnabled())
|
|
{
|
|
TD.CompensationState(tokenData.DisplayName, tokenData.CompensationState.ToString());
|
|
}
|
|
|
|
if (this.Body != null)
|
|
{
|
|
context.ScheduleActivity(this.Body, new CompletionCallback(OnBodyExecutionComplete));
|
|
}
|
|
else
|
|
{
|
|
//empty body case. Assume the body has completed successfully
|
|
tokenData.CompensationState = CompensationState.Completed;
|
|
if (TD.CompensationStateIsEnabled())
|
|
{
|
|
TD.CompensationState(tokenData.DisplayName, tokenData.CompensationState.ToString());
|
|
}
|
|
|
|
ScheduleSecondaryRoot(context, compensationExtension, tokenData);
|
|
}
|
|
}
|
|
|
|
void OnBodyExecutionComplete(NativeActivityContext context, ActivityInstance completedInstance)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
CompensationTokenData token = compensationExtension.Get(this.currentCompensationId.Get(context));
|
|
Fx.Assert(token != null, "CompensationTokenData must be valid");
|
|
|
|
if (completedInstance.State == ActivityInstanceState.Closed)
|
|
{
|
|
token.CompensationState = CompensationState.Completed;
|
|
if (TD.CompensationStateIsEnabled())
|
|
{
|
|
TD.CompensationState(token.DisplayName, token.CompensationState.ToString());
|
|
}
|
|
|
|
if (context.IsCancellationRequested)
|
|
{
|
|
token.CompensationState = CompensationState.Compensating;
|
|
}
|
|
}
|
|
else if (completedInstance.State == ActivityInstanceState.Canceled || completedInstance.State == ActivityInstanceState.Faulted)
|
|
{
|
|
// we check for faulted as well for one odd case where an exception can be thrown from the body activity itself.
|
|
token.CompensationState = CompensationState.Canceling;
|
|
}
|
|
else
|
|
{
|
|
Fx.Assert(false, "completedInstance in unexpected state");
|
|
}
|
|
|
|
ScheduleSecondaryRoot(context, compensationExtension, token);
|
|
}
|
|
|
|
void ScheduleSecondaryRoot(NativeActivityContext context, CompensationExtension compensationExtension, CompensationTokenData token)
|
|
{
|
|
if (token.ParentCompensationId != CompensationToken.RootCompensationId)
|
|
{
|
|
CompensationTokenData parentToken = compensationExtension.Get(token.ParentCompensationId);
|
|
Fx.Assert(parentToken != null, "parentToken must be valid");
|
|
|
|
parentToken.ExecutionTracker.Add(token);
|
|
}
|
|
else
|
|
{
|
|
CompensationTokenData parentToken = compensationExtension.Get(CompensationToken.RootCompensationId);
|
|
Fx.Assert(parentToken != null, "parentToken must be valid");
|
|
|
|
parentToken.ExecutionTracker.Add(token);
|
|
}
|
|
|
|
// If we are going to Cancel, don't set the out arg...
|
|
if (Result != null && token.CompensationState == CompensationState.Completed)
|
|
{
|
|
Result.Set(context, this.currentCompensationToken.Get(context));
|
|
}
|
|
|
|
Fx.Assert(token.BookmarkTable[CompensationBookmarkName.OnSecondaryRootScheduled] == null, "Bookmark should not be already initialized in the bookmark table.");
|
|
token.BookmarkTable[CompensationBookmarkName.OnSecondaryRootScheduled] = context.CreateBookmark(new BookmarkCallback(OnSecondaryRootScheduled));
|
|
|
|
this.compensationId.Set(context, token.CompensationId);
|
|
|
|
context.ScheduleSecondaryRoot(CompensationParticipant, context.Environment);
|
|
}
|
|
|
|
void OnSecondaryRootScheduled(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
long compensationId = (long)value;
|
|
|
|
CompensationTokenData compensationToken = compensationExtension.Get(compensationId);
|
|
Fx.Assert(compensationToken != null, "CompensationTokenData must be valid");
|
|
|
|
if (compensationToken.CompensationState == CompensationState.Canceling)
|
|
{
|
|
Fx.Assert(compensationToken.BookmarkTable[CompensationBookmarkName.Canceled] == null, "Bookmark should not be already initialized in the bookmark table.");
|
|
compensationToken.BookmarkTable[CompensationBookmarkName.Canceled] = context.CreateBookmark(new BookmarkCallback(OnCanceledOrCompensated));
|
|
|
|
compensationExtension.NotifyMessage(context, compensationToken.CompensationId, CompensationBookmarkName.OnCancellation);
|
|
}
|
|
else if (compensationToken.CompensationState == CompensationState.Compensating)
|
|
{
|
|
Fx.Assert(compensationToken.BookmarkTable[CompensationBookmarkName.Compensated] == null, "Bookmark should not be already initialized in the bookmark table.");
|
|
compensationToken.BookmarkTable[CompensationBookmarkName.Compensated] = context.CreateBookmark(new BookmarkCallback(OnCanceledOrCompensated));
|
|
|
|
compensationExtension.NotifyMessage(context, compensationToken.CompensationId, CompensationBookmarkName.OnCompensation);
|
|
}
|
|
}
|
|
|
|
void OnCanceledOrCompensated(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
long compensationId = (long)value;
|
|
|
|
CompensationTokenData compensationToken = compensationExtension.Get(compensationId);
|
|
Fx.Assert(compensationToken != null, "CompensationTokenData must be valid");
|
|
|
|
switch (compensationToken.CompensationState)
|
|
{
|
|
case CompensationState.Canceling:
|
|
compensationToken.CompensationState = CompensationState.Canceled;
|
|
break;
|
|
case CompensationState.Compensating:
|
|
compensationToken.CompensationState = CompensationState.Compensated;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (TD.CompensationStateIsEnabled())
|
|
{
|
|
TD.CompensationState(compensationToken.DisplayName, compensationToken.CompensationState.ToString());
|
|
}
|
|
|
|
AppCompletionCleanup(context, compensationExtension, compensationToken);
|
|
|
|
// Mark the activity as canceled.
|
|
context.MarkCanceled();
|
|
}
|
|
|
|
void AppCompletionCleanup(NativeActivityContext context, CompensationExtension compensationExtension, CompensationTokenData compensationToken)
|
|
{
|
|
Fx.Assert(compensationToken != null, "CompensationTokenData must be valid");
|
|
|
|
// Remove the token from the parent!
|
|
if (compensationToken.ParentCompensationId != CompensationToken.RootCompensationId)
|
|
{
|
|
CompensationTokenData parentToken = compensationExtension.Get(compensationToken.ParentCompensationId);
|
|
Fx.Assert(parentToken != null, "parentToken must be valid");
|
|
|
|
parentToken.ExecutionTracker.Remove(compensationToken);
|
|
}
|
|
else
|
|
{
|
|
// remove from workflow root...
|
|
CompensationTokenData parentToken = compensationExtension.Get(CompensationToken.RootCompensationId);
|
|
Fx.Assert(parentToken != null, "parentToken must be valid");
|
|
|
|
parentToken.ExecutionTracker.Remove(compensationToken);
|
|
}
|
|
|
|
compensationToken.RemoveBookmark(context, CompensationBookmarkName.Canceled);
|
|
compensationToken.RemoveBookmark(context, CompensationBookmarkName.Compensated);
|
|
|
|
// Remove the token from the extension...
|
|
compensationExtension.Remove(compensationToken.CompensationId);
|
|
}
|
|
}
|
|
|
|
// In order to run in partial trust, we can't have lambda expressions that reference local variables. So this
|
|
// code activity replaces the lambda expression in this statement:
|
|
// While(env => (assertFlag.Get(env) != false) && index.Get(env) < elements.Get(env).Count())
|
|
class WhileExpression : CodeActivity<bool>
|
|
{
|
|
public InArgument<bool> AssertFlag
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public InArgument<int> Index
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public InArgument<IEnumerable<Activity>> Elements
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
protected override void CacheMetadata(CodeActivityMetadata metadata)
|
|
{
|
|
RuntimeArgument assertFlagArgument = new RuntimeArgument("AssertFlag", typeof(bool), ArgumentDirection.In);
|
|
if (this.AssertFlag == null)
|
|
{
|
|
this.AssertFlag = new InArgument<bool>();
|
|
}
|
|
metadata.Bind(this.AssertFlag, assertFlagArgument);
|
|
|
|
RuntimeArgument indexArgument = new RuntimeArgument("Index", typeof(int), ArgumentDirection.In);
|
|
if (this.Index == null)
|
|
{
|
|
this.Index = new InArgument<int>();
|
|
}
|
|
metadata.Bind(this.Index, indexArgument);
|
|
|
|
RuntimeArgument elementsArgument = new RuntimeArgument("Elements", typeof(IEnumerable<Activity>), ArgumentDirection.In);
|
|
if (this.Elements == null)
|
|
{
|
|
this.Elements = new InArgument<IEnumerable<Activity>>();
|
|
}
|
|
metadata.Bind(this.Elements, elementsArgument);
|
|
|
|
RuntimeArgument resultArgument = new RuntimeArgument("Result", typeof(bool), ArgumentDirection.Out);
|
|
if (this.Result == null)
|
|
{
|
|
this.Result = new OutArgument<bool>();
|
|
}
|
|
metadata.Bind(this.Result, resultArgument);
|
|
|
|
metadata.SetArgumentsCollection(
|
|
new Collection<RuntimeArgument>
|
|
{
|
|
assertFlagArgument,
|
|
indexArgument,
|
|
elementsArgument,
|
|
resultArgument
|
|
});
|
|
}
|
|
|
|
protected override bool Execute(CodeActivityContext context)
|
|
{
|
|
// While(env => (assertFlag.Get(env) != false) && index.Get(env) < elements.Get(env).Count())
|
|
return ((this.AssertFlag.Get(context) != false) && (this.Index.Get(context) < this.Elements.Get(context).Count()));
|
|
}
|
|
}
|
|
|
|
|
|
// If(env => (elements.Get(env).ElementAt(index.Get(env))).GetType() == typeof(CompensationParticipant))
|
|
class IfExpression : CodeActivity<bool>
|
|
{
|
|
public InArgument<IEnumerable<Activity>> Elements
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public InArgument<int> Index
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
protected override void CacheMetadata(CodeActivityMetadata metadata)
|
|
{
|
|
RuntimeArgument elementsArgument = new RuntimeArgument("Elements", typeof(IEnumerable<Activity>), ArgumentDirection.In);
|
|
if (this.Elements == null)
|
|
{
|
|
this.Elements = new InArgument<IEnumerable<Activity>>();
|
|
}
|
|
metadata.Bind(this.Elements, elementsArgument);
|
|
|
|
RuntimeArgument indexArgument = new RuntimeArgument("Index", typeof(int), ArgumentDirection.In);
|
|
if (this.Index == null)
|
|
{
|
|
this.Index = new InArgument<int>();
|
|
}
|
|
metadata.Bind(this.Index, indexArgument);
|
|
|
|
RuntimeArgument resultArgument = new RuntimeArgument("Result", typeof(bool), ArgumentDirection.Out);
|
|
if (this.Result == null)
|
|
{
|
|
this.Result = new OutArgument<bool>();
|
|
}
|
|
metadata.Bind(this.Result, resultArgument);
|
|
|
|
metadata.SetArgumentsCollection(
|
|
new Collection<RuntimeArgument>
|
|
{
|
|
indexArgument,
|
|
elementsArgument,
|
|
resultArgument
|
|
});
|
|
}
|
|
|
|
protected override bool Execute(CodeActivityContext context)
|
|
{
|
|
// If(env => (elements.Get(env).ElementAt(index.Get(env))).GetType() == typeof(CompensationParticipant))
|
|
return (this.Elements.Get(context).ElementAt(this.Index.Get(context)).GetType() == typeof(CompensationParticipant));
|
|
}
|
|
}
|
|
}
|