//----------------------------------------------------------------------------- // 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 CreateFunc(XamlReader reader, Type returnType) { FuncFactory factory = CreateFactory(null, reader, returnType); return factory.GetFunc(); } public static Func CreateFunc(XamlReader reader) where T : class { FuncFactory factory = new FuncFactory(null, reader); return factory.GetTypedFunc(); } internal IList 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 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 : 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 GetFunc() { return (Func)Evaluate; } internal Func 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; } } }