e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
118 lines
4.5 KiB
C#
118 lines
4.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.Activities.Runtime
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Runtime.Serialization;
|
|
using System.Runtime;
|
|
using System.Security;
|
|
|
|
[DataContract]
|
|
class FuncCompletionCallbackWrapper<T> : CompletionCallbackWrapper
|
|
{
|
|
static readonly Type callbackType = typeof(CompletionCallback<T>);
|
|
static readonly Type[] callbackParameterTypes = new Type[] { typeof(NativeActivityContext), typeof(ActivityInstance), typeof(T) };
|
|
|
|
T resultValue;
|
|
|
|
public FuncCompletionCallbackWrapper(CompletionCallback<T> callback, ActivityInstance owningInstance)
|
|
: base(callback, owningInstance)
|
|
{
|
|
this.NeedsToGatherOutputs = true;
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "resultValue")]
|
|
internal T SerializedResultValue
|
|
{
|
|
get { return this.resultValue; }
|
|
set { this.resultValue = value; }
|
|
}
|
|
|
|
int GetResultId(ActivityWithResult activity)
|
|
{
|
|
if (activity.Result != null)
|
|
{
|
|
return activity.Result.Id;
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < activity.RuntimeArguments.Count; i++)
|
|
{
|
|
RuntimeArgument argument = activity.RuntimeArguments[i];
|
|
|
|
if (argument.IsResult)
|
|
{
|
|
return argument.Id;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
protected override void GatherOutputs(ActivityInstance completedInstance)
|
|
{
|
|
int resultId = -1;
|
|
|
|
if (completedInstance.Activity.HandlerOf != null)
|
|
{
|
|
DelegateOutArgument resultArgument = completedInstance.Activity.HandlerOf.GetResultArgument();
|
|
if (resultArgument != null)
|
|
{
|
|
resultId = resultArgument.Id;
|
|
}
|
|
else
|
|
{
|
|
ActivityWithResult activity = completedInstance.Activity as ActivityWithResult;
|
|
// for auto-generated results, we should bind the value from the Handler if available
|
|
if (activity != null && TypeHelper.AreTypesCompatible(activity.ResultType, typeof(T)))
|
|
{
|
|
resultId = GetResultId(activity);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Fx.Assert(completedInstance.Activity is ActivityWithResult, "should only be using FuncCompletionCallbackWrapper with ActivityFunc and ActivityWithResult");
|
|
resultId = GetResultId((ActivityWithResult)completedInstance.Activity);
|
|
}
|
|
|
|
if (resultId >= 0)
|
|
{
|
|
Location location = completedInstance.Environment.GetSpecificLocation(resultId);
|
|
Location<T> typedLocation = location as Location<T>;
|
|
|
|
if (typedLocation != null)
|
|
{
|
|
this.resultValue = typedLocation.Value;
|
|
}
|
|
else if (location != null)
|
|
{
|
|
this.resultValue = TypeHelper.Convert<T>(location.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback",
|
|
Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
|
|
[SecuritySafeCritical]
|
|
protected internal override void Invoke(NativeActivityContext context, ActivityInstance completedInstance)
|
|
{
|
|
// Call the EnsureCallback overload that also looks for SomeMethod<T> where T is the result type
|
|
// and the signature matches.
|
|
EnsureCallback(callbackType, callbackParameterTypes, callbackParameterTypes[2]);
|
|
CompletionCallback<T> completionCallback = (CompletionCallback<T>)this.Callback;
|
|
completionCallback(context, completedInstance, this.resultValue);
|
|
}
|
|
|
|
protected override void OnSerializingGenericCallback()
|
|
{
|
|
ValidateCallbackResolution(callbackType, callbackParameterTypes, callbackParameterTypes[2]);
|
|
}
|
|
}
|
|
}
|