e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
120 lines
5.0 KiB
C#
120 lines
5.0 KiB
C#
//----------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------
|
|
|
|
namespace System.Activities.Expressions
|
|
{
|
|
using System.Activities;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Reflection;
|
|
using System.Runtime;
|
|
using System.Runtime.Collections;
|
|
using System.Windows.Markup;
|
|
using System.Linq.Expressions;
|
|
using System.Collections.Generic;
|
|
using System.Activities.Validation;
|
|
using System.Threading;
|
|
|
|
[SuppressMessage(FxCop.Category.Naming, FxCop.Rule.IdentifiersShouldNotMatchKeywords,
|
|
Justification = "Optimizing for XAML naming. VB imperative users will [] qualify (e.g. New [New])")]
|
|
[SuppressMessage(FxCop.Category.Naming, FxCop.Rule.IdentifiersShouldNotHaveIncorrectSuffix,
|
|
Justification = "Optimizing for XAML naming.")]
|
|
[ContentProperty("Arguments")]
|
|
public sealed class New<TResult> : CodeActivity<TResult>
|
|
{
|
|
Collection<Argument> arguments;
|
|
Func<object[], TResult> function;
|
|
ConstructorInfo constructorInfo;
|
|
static MruCache<ConstructorInfo, Func<object[], TResult>> funcCache =
|
|
new MruCache<ConstructorInfo, Func<object[], TResult>>(MethodCallExpressionHelper.FuncCacheCapacity);
|
|
static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
|
|
|
|
[SuppressMessage(FxCop.Category.Naming, FxCop.Rule.PropertyNamesShouldNotMatchGetMethods,
|
|
Justification = "Optimizing for XAML naming.")]
|
|
public Collection<Argument> Arguments
|
|
{
|
|
get
|
|
{
|
|
if (this.arguments == null)
|
|
{
|
|
this.arguments = new ValidatingCollection<Argument>
|
|
{
|
|
// disallow null values
|
|
OnAddValidationCallback = item =>
|
|
{
|
|
if (item == null)
|
|
{
|
|
throw FxTrace.Exception.ArgumentNull("item");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return this.arguments;
|
|
}
|
|
}
|
|
|
|
protected override void CacheMetadata(CodeActivityMetadata metadata)
|
|
{
|
|
bool foundError = false;
|
|
ConstructorInfo oldConstructorInfo = this.constructorInfo;
|
|
|
|
// Loop through each argument, validate it, and if validation
|
|
// passed expose it to the metadata
|
|
Type[] types = new Type[this.Arguments.Count];
|
|
for (int i = 0; i < this.Arguments.Count; i++)
|
|
{
|
|
Argument argument = this.Arguments[i];
|
|
if (argument == null || argument.Expression == null)
|
|
{
|
|
metadata.AddValidationError(SR.ArgumentRequired("Arguments", typeof(New<TResult>)));
|
|
foundError = true;
|
|
}
|
|
else
|
|
{
|
|
RuntimeArgument runtimeArgument = new RuntimeArgument("Argument" + i, this.arguments[i].ArgumentType, this.arguments[i].Direction, true);
|
|
metadata.Bind(this.arguments[i], runtimeArgument);
|
|
metadata.AddArgument(runtimeArgument);
|
|
types[i] = this.Arguments[i].Direction == ArgumentDirection.In ? this.Arguments[i].ArgumentType : this.Arguments[i].ArgumentType.MakeByRefType();
|
|
}
|
|
}
|
|
|
|
// If we didn't find any errors in the arguments then
|
|
// we can look for an appropriate constructor.
|
|
if (!foundError)
|
|
{
|
|
constructorInfo = typeof(TResult).GetConstructor(types);
|
|
if (constructorInfo == null && (!typeof(TResult).IsValueType || types.Length > 0))
|
|
{
|
|
metadata.AddValidationError(SR.ConstructorInfoNotFound(typeof(TResult).Name));
|
|
}
|
|
else if ((this.constructorInfo != oldConstructorInfo) || (this.function == null))
|
|
{
|
|
this.function = MethodCallExpressionHelper.GetFunc<TResult>(metadata, constructorInfo, funcCache, locker);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override TResult Execute(CodeActivityContext context)
|
|
{
|
|
object[] objects = new object[this.Arguments.Count];
|
|
for (int i = 0; i < this.Arguments.Count; i++)
|
|
{
|
|
objects[i] = this.Arguments[i].Get(context);
|
|
}
|
|
TResult result = this.function(objects);
|
|
|
|
for (int i = 0; i < this.Arguments.Count; i++)
|
|
{
|
|
Argument argument = this.Arguments[i];
|
|
if (argument.Direction == ArgumentDirection.InOut || argument.Direction == ArgumentDirection.Out)
|
|
{
|
|
argument.Set(context, objects[i]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|
|
}
|