File: System\Activities\XamlIntegration\FuncFactory.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.Activities.XamlIntegration
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Reflection;
    using System.Runtime;
    using System.Windows.Markup;
    using System.Xaml;
 
    abstract class FuncFactory
    {
        public static Func<object> CreateFunc(XamlReader reader, Type returnType)
        {
            FuncFactory factory = CreateFactory(null, reader, returnType);
            return factory.GetFunc();
        }
 
        public static Func<T> CreateFunc<T>(XamlReader reader) where T : class
        {
            FuncFactory<T> factory = new FuncFactory<T>(null, reader);
            return factory.GetTypedFunc();
        }
 
        internal IList<NamespaceDeclaration> ParentNamespaces
        {
            get;
            set;
        }
 
        internal XamlNodeList Nodes
        {
            get;
            set;
        }
 
        // Back-compat switch: we don't want to copy parent settings on Activity/DynamicActivity
        internal bool IgnoreParentSettings
        {
            get;
            set;
        }
 
        internal abstract Func<object> GetFunc();
 
        internal static FuncFactory CreateFactory(XamlReader xamlReader, IServiceProvider context)
        {
            IXamlObjectWriterFactory objectWriterFactory = context.GetService(typeof(IXamlObjectWriterFactory)) as IXamlObjectWriterFactory;
            IProvideValueTarget provideValueService = context.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
 
            Type propertyType = null;
            //
            // IProvideValueTarget.TargetProperty can return DP, Attached Property or MemberInfo for clr property
            // In this case it should always be a regular clr property here - we are always targeting Activity.Body.
            PropertyInfo propertyInfo = provideValueService.TargetProperty as PropertyInfo;
 
            if (propertyInfo != null)
            {
                propertyType = propertyInfo.PropertyType;
            }
 
            FuncFactory funcFactory = CreateFactory(objectWriterFactory, xamlReader, propertyType.GetGenericArguments());
            return funcFactory;
        }
 
        // Back-compat workaround: returnType should only be a single value. But in 4.0 we didn't
        // validate this; we just passed the array in to MakeGenericType, which would throw if there
        // were multiple values. To preserve the same exception, we allow passing in an array here.
        static FuncFactory CreateFactory(IXamlObjectWriterFactory objectWriterFactory, XamlReader xamlReader, params Type[] returnType)
        {
            Type closedType = typeof(FuncFactory<>).MakeGenericType(returnType);
            return (FuncFactory)Activator.CreateInstance(closedType, objectWriterFactory, xamlReader);
        }
    }
 
    class FuncFactory<T> : FuncFactory where T : class
    {
        IXamlObjectWriterFactory objectWriterFactory;
 
        public FuncFactory(IXamlObjectWriterFactory objectWriterFactory, XamlReader reader)
        {
            this.objectWriterFactory = objectWriterFactory;
            this.Nodes = new XamlNodeList(reader.SchemaContext);
            XamlServices.Transform(reader, this.Nodes.Writer);
        }
 
        internal T Evaluate()
        {
            XamlObjectWriter writer = GetWriter();
            XamlServices.Transform(this.Nodes.GetReader(), writer);
            return (T)writer.Result;
        }
 
        internal override Func<object> GetFunc()
        {
            return (Func<T>)Evaluate;
        }
 
        internal Func<T> GetTypedFunc()
        {
            return Evaluate;
        }
 
        XamlObjectWriter GetWriter()
        {
            if (this.objectWriterFactory != null)
            {
                return this.objectWriterFactory.GetXamlObjectWriter(GetObjectWriterSettings());
            }
            else
            {
                return new XamlObjectWriter(this.Nodes.Writer.SchemaContext);
            }
        }
 
        XamlObjectWriterSettings GetObjectWriterSettings()
        {
            if (IgnoreParentSettings)
            {
                return new XamlObjectWriterSettings();
            }
            XamlObjectWriterSettings result = new XamlObjectWriterSettings(this.objectWriterFactory.GetParentSettings());
            // The delegate settings are already stripped by XOW. Some other settings don't make sense to copy.
            result.ExternalNameScope = null;
            result.RegisterNamesOnExternalNamescope = false;
            result.RootObjectInstance = null;
            result.SkipProvideValueOnRoot = false;
            return result;
        }
    }
}