e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
193 lines
5.9 KiB
C#
193 lines
5.9 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.Activities.Statements
|
|
{
|
|
using System.Activities.Validation;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Runtime.Collections;
|
|
using System.Windows.Markup;
|
|
using System.Runtime;
|
|
using System.Activities.Expressions;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
|
|
[ContentProperty("Parameters")]
|
|
public sealed class InvokeMethod : AsyncCodeActivity
|
|
{
|
|
Collection<Argument> parameters;
|
|
Collection<Type> genericTypeArguments;
|
|
|
|
MethodResolver methodResolver;
|
|
MethodExecutor methodExecutor;
|
|
RuntimeArgument resultArgument;
|
|
|
|
static MruCache<MethodInfo, Func<object, object[], object>> funcCache =
|
|
new MruCache<MethodInfo, Func<object, object[], object>>(MethodCallExpressionHelper.FuncCacheCapacity);
|
|
static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
|
|
|
|
|
|
public Collection<Type> GenericTypeArguments
|
|
{
|
|
get
|
|
{
|
|
if (this.genericTypeArguments == null)
|
|
{
|
|
this.genericTypeArguments = new ValidatingCollection<Type>
|
|
{
|
|
// disallow null values
|
|
OnAddValidationCallback = item =>
|
|
{
|
|
if (item == null)
|
|
{
|
|
throw FxTrace.Exception.ArgumentNull("item");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return this.genericTypeArguments;
|
|
}
|
|
}
|
|
|
|
public string MethodName
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public Collection<Argument> Parameters
|
|
{
|
|
get
|
|
{
|
|
if (this.parameters == null)
|
|
{
|
|
this.parameters = new ValidatingCollection<Argument>
|
|
{
|
|
// disallow null values
|
|
OnAddValidationCallback = item =>
|
|
{
|
|
if (item == null)
|
|
{
|
|
throw FxTrace.Exception.ArgumentNull("item");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return this.parameters;
|
|
}
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
public OutArgument Result
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
public InArgument TargetObject
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
public Type TargetType
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DefaultValue(false)]
|
|
public bool RunAsynchronously
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
|
|
protected override void CacheMetadata(CodeActivityMetadata metadata)
|
|
{
|
|
Collection<RuntimeArgument> arguments = new Collection<RuntimeArgument>();
|
|
|
|
Type targetObjectType = TypeHelper.ObjectType;
|
|
|
|
if (this.TargetObject != null)
|
|
{
|
|
targetObjectType = this.TargetObject.ArgumentType;
|
|
}
|
|
|
|
RuntimeArgument targetObjectArgument = new RuntimeArgument("TargetObject", targetObjectType, ArgumentDirection.In);
|
|
metadata.Bind(this.TargetObject, targetObjectArgument);
|
|
arguments.Add(targetObjectArgument);
|
|
|
|
Type resultType = TypeHelper.ObjectType;
|
|
|
|
if (this.Result != null)
|
|
{
|
|
resultType = this.Result.ArgumentType;
|
|
}
|
|
|
|
this.resultArgument = new RuntimeArgument("Result", resultType, ArgumentDirection.Out);
|
|
metadata.Bind(this.Result, this.resultArgument);
|
|
arguments.Add(resultArgument);
|
|
|
|
// Parameters are named according to MethodInfo name if DetermineMethodInfo
|
|
// succeeds, otherwise arbitrary names are used.
|
|
this.methodResolver = CreateMethodResolver();
|
|
this.methodResolver.DetermineMethodInfo(metadata, funcCache, locker, ref this.methodExecutor);
|
|
this.methodResolver.RegisterParameters(arguments);
|
|
|
|
metadata.SetArgumentsCollection(arguments);
|
|
|
|
this.methodResolver.Trace();
|
|
|
|
if (this.methodExecutor != null)
|
|
{
|
|
this.methodExecutor.Trace(this);
|
|
}
|
|
}
|
|
|
|
|
|
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
|
|
{
|
|
return this.methodExecutor.BeginExecuteMethod(context, callback, state);
|
|
}
|
|
|
|
protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
|
|
{
|
|
this.methodExecutor.EndExecuteMethod(context, result);
|
|
}
|
|
|
|
MethodResolver CreateMethodResolver()
|
|
{
|
|
MethodResolver resolver = new MethodResolver
|
|
{
|
|
MethodName = this.MethodName,
|
|
RunAsynchronously = this.RunAsynchronously,
|
|
TargetType = this.TargetType,
|
|
TargetObject = this.TargetObject,
|
|
GenericTypeArguments = this.GenericTypeArguments,
|
|
Parameters = this.Parameters,
|
|
Result = this.resultArgument,
|
|
Parent = this
|
|
};
|
|
|
|
if (this.Result != null)
|
|
{
|
|
resolver.ResultType = this.Result.ArgumentType;
|
|
}
|
|
else
|
|
{
|
|
resolver.ResultType = typeof(object);
|
|
}
|
|
|
|
return resolver;
|
|
}
|
|
|
|
}
|
|
}
|