File: System\Activities\InArgument.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.Activities
{
    using System;
    using System.Activities.Expressions;
    using System.Activities.Runtime;
    using System.Activities.XamlIntegration;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq.Expressions;
    using System.Runtime;
    using System.Windows.Markup;
    using System.Diagnostics.CodeAnalysis;
 
    public abstract class InArgument : Argument
    {
        internal InArgument()
            : base()
        {
            this.Direction = ArgumentDirection.In;
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "Subclass needed to enforce rules about which directions can be referenced.")]
        public static InArgument CreateReference(InArgument argumentToReference, string referencedArgumentName)
        {
            if (argumentToReference == null)
            {
                throw FxTrace.Exception.ArgumentNull("argumentToReference");
            }
 
            if (string.IsNullOrEmpty(referencedArgumentName))
            {
                throw FxTrace.Exception.ArgumentNullOrEmpty("referencedArgumentName");
            }
 
            return (InArgument)ActivityUtilities.CreateReferenceArgument(argumentToReference.ArgumentType, ArgumentDirection.In, referencedArgumentName);
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "Subclass needed to enforce rules about which directions can be referenced.")]
        public static InArgument CreateReference(InOutArgument argumentToReference, string referencedArgumentName)
        {
            if (argumentToReference == null)
            {
                throw FxTrace.Exception.ArgumentNull("argumentToReference");
            }
 
            if (string.IsNullOrEmpty(referencedArgumentName))
            {
                throw FxTrace.Exception.ArgumentNullOrEmpty("referencedArgumentName");
            }
 
            // Note that we explicitly pass In since we want an InArgument created
            return (InArgument)ActivityUtilities.CreateReferenceArgument(argumentToReference.ArgumentType, ArgumentDirection.In, referencedArgumentName);
        }
    }
 
    [ContentProperty("Expression")]
    [TypeConverter(typeof(InArgumentConverter))]
    [ValueSerializer(typeof(ArgumentValueSerializer))]
    public sealed class InArgument<T> : InArgument
    {
        public InArgument(Variable variable)
            : this()
        {
            if (variable != null)
            {
                this.Expression = new VariableValue<T> { Variable = variable };
            }
        }
 
        public InArgument(DelegateArgument delegateArgument)
            : this()
        {
            if (delegateArgument != null)
            {
                this.Expression = new DelegateArgumentValue<T> { DelegateArgument = delegateArgument };
            }
        }
 
        public InArgument(T constValue)
            : this()
        {
            this.Expression = new Literal<T> { Value = constValue }; 
        }
 
        public InArgument(Expression<Func<ActivityContext, T>> expression)
            : this()
        {
            if (expression != null)
            {                
                this.Expression = new LambdaValue<T>(expression);
            }
        }
 
        public InArgument(Activity<T> expression)
            : this()
        {
            this.Expression = expression;
        }
 
 
        public InArgument()
            : base()
        {
            this.ArgumentType = typeof(T);
        }
 
        [DefaultValue(null)]
        public new Activity<T> Expression
        {
            get;
            set;
        }
 
        internal override ActivityWithResult ExpressionCore
        {
            get
            {
                return this.Expression;
            }
            set
            {
                if (value == null)
                {
                    this.Expression = null;
                    return;
                }
 
                if (value is Activity<T>)
                {
                    this.Expression = (Activity<T>)value;
                }
                else
                {
                    // We do not verify compatibility here. We will do that
                    // during CacheMetadata in Argument.Validate.
                    this.Expression = new ActivityWithResultWrapper<T>(value);
                }
            }
        }
 
        public static implicit operator InArgument<T>(Variable variable)
        {
            return FromVariable(variable);
        }
 
        public static implicit operator InArgument<T>(DelegateArgument delegateArgument)
        {
            return FromDelegateArgument(delegateArgument);
        }
 
        public static implicit operator InArgument<T>(Activity<T> expression)
        {
            return FromExpression(expression);
        }
 
        public static implicit operator InArgument<T>(T constValue)
        {
            return FromValue(constValue);
        }
 
        public static InArgument<T> FromVariable(Variable variable)
        {
            if (variable == null)
            {
                throw FxTrace.Exception.ArgumentNull("variable");
            }
            return new InArgument<T>(variable);
        }
 
        public static InArgument<T> FromDelegateArgument(DelegateArgument delegateArgument)
        {
            if (delegateArgument == null)
            {
                throw FxTrace.Exception.ArgumentNull("delegateArgument");
            }
            return new InArgument<T>(delegateArgument);
        }
 
        public static InArgument<T> FromExpression(Activity<T> expression)
        {
            if (expression == null)
            {
                throw FxTrace.Exception.ArgumentNull("expression");
            }
 
            return new InArgument<T>(expression);
        }
 
        public static InArgument<T> FromValue(T constValue)
        {
            return new InArgument<T>
                {
                    Expression = new Literal<T> { Value = constValue }
                };
        }
 
        // Soft-Link: This method is referenced through reflection by
        // ExpressionUtilities.TryRewriteLambdaExpression.  Update that
        // file if the signature changes.
        public new T Get(ActivityContext context)
        {
            return Get<T>(context);
        }
 
        public void Set(ActivityContext context, T value)
        {
            if (context == null)
            {
                throw FxTrace.Exception.ArgumentNull("context");
            }
 
            context.SetValue(this, value);
        }
 
        internal override Location CreateDefaultLocation()
        {
            return Argument.CreateLocation<T>();
        }
 
        internal override bool TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance activityInstance, ActivityExecutor executor)
        {
            Fx.Assert(this.Expression != null, "This should only be called for non-empty bindings");
 
            Location<T> location = Argument.CreateLocation<T>();
            targetEnvironment.Declare(this.RuntimeArgument, location, activityInstance);
 
            if (this.Expression.UseOldFastPath)
            {
                location.Value = executor.ExecuteInResolutionContext<T>(activityInstance, this.Expression);
                return true;
            }
            else
            {
                return false;
            }
        }
 
        internal override void Declare(LocationEnvironment targetEnvironment, ActivityInstance targetActivityInstance)
        {
            targetEnvironment.Declare(this.RuntimeArgument, CreateDefaultLocation(), targetActivityInstance);
        }
    }
}