/Labs/Microsoft.Activities.Extensions/Microsoft.Activities.Extensions/StrictXamlHelper.cs
C# | 241 lines | 112 code | 23 blank | 106 comment | 9 complexity | cbe017db4d91ecbe76fda90322cc77ec MD5 | raw file
- // --------------------------------------------------------------------------------------------------------------------
- // <copyright file="StrictXamlHelper.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // --------------------------------------------------------------------------------------------------------------------
-
- namespace Microsoft.Activities.Extensions
- {
- using System;
- using System.Activities;
- using System.Activities.XamlIntegration;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Reflection;
- using System.Xaml;
- using System.Xaml.Permissions;
- using System.Xml;
-
- /// <summary>
- /// Provides helper methods that will apply normal CLR rules for assembly resolution when loading XAML
- /// </summary>
- /// <remarks>
- /// The standard _XamlStaticHelper class generated by the XamlAppDef build task does not apply
- /// standard CLR rules when loading assemblies referenced by XAML.
- /// For more details see http://blogs.msdn.com/b/rjacobs/archive/2011/01/07/wf4-spike-activity-versioning-gac-and-loose-xaml.aspx
- /// For an example of how to use this class see the XAMLAssemblyResolution Example under the Examples folder
- /// </remarks>
- public static class StrictXamlHelper
- {
- #region Static Fields
-
- /// <summary>
- /// The schema context field.
- /// </summary>
- private static WeakReference schemaContextField;
-
- #endregion
-
- #region Public Properties
-
- /// <summary>
- /// Gets the standard list of referenced assemblies for C# projects.
- /// </summary>
- /// <remarks>
- /// Workflows typically reference a standard list of assemblies.
- /// This list will make it easier to create a reference list by combining the two
- /// </remarks>
- /// <example>
- /// ReferencedAssemblies property that adds the StandardReferencedAssemblies collection to it's own
- /// <code source="Examples\CSDocExamples\WorkflowCompiled.cs" lang="CSharp" />
- /// </example>
- public static IEnumerable<string> StandardCSharpReferencedAssemblies
- {
- get
- {
- var list = new List<string>
- {
- "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
- };
- list.AddRange(StandardVBReferencedAssemblies);
- return list;
- }
- }
-
- /// <summary>
- /// Gets the standard list of referenced assemblies for VB projects.
- /// </summary>
- /// <remarks>
- /// Workflows typically reference a standard list of assemblies.
- /// This list will make it easier to create a reference list by combining the two
- /// </remarks>
- public static IEnumerable<string> StandardVBReferencedAssemblies
- {
- get
- {
- return new List<string>
- {
- "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
- "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
- "System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- "System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
- };
- }
- }
-
- #endregion
-
- #region Public Methods and Operators
-
- /// <summary>
- /// Loads loose XAML and pre-loads the assemblies to ensure correct CLR binding
- /// </summary>
- /// <param name="activityXaml">
- /// The activity xaml.
- /// </param>
- /// <param name="assemblies">
- /// The assemblies.
- /// </param>
- /// <returns>
- /// A <see cref="System.Activities.DynamicActivity"/>
- /// </returns>
- /// <remarks>
- /// ActivityXamlServices.Load will load referenced assemblies using only the assembly name found in the XAML file.
- /// The default behavior stores only partial names for references. This means that when the assembly is loaded it
- /// will load with a partial name which could result in an unexpected version or entirely different assembly being
- /// loaded.
- /// As an alternative you can use the <qualifyAssembly> element in your config file to ensure the correct
- /// assembly is loaded
- /// </remarks>
- /// <example>
- /// A class that runs loose XAML with an <see cref="XamlAssemblyResolutionOption"/>
- /// <code source="Examples\CSDocExamples\LooseXamlExample.cs" lang="CSharp">
- /// </code>
- /// </example>
- [DebuggerNonUserCode]
- public static Activity ActivityLoad(string activityXaml, IList<string> assemblies)
- {
- LoadAssemblies(assemblies);
- return ActivityXamlServices.Load(activityXaml);
- }
-
- /// <summary>
- /// Initializes the Component with strict assembly resolution rules
- /// </summary>
- /// <param name="component">
- /// The component.
- /// </param>
- /// <param name="resourceName">
- /// The resource Name.
- /// </param>
- /// <param name="assemblies">
- /// The referenced assemblies.
- /// </param>
- /// <typeparam name="T">
- /// The type of activity you are initializing
- /// </typeparam>
- /// <returns>
- /// true if content loaded
- /// </returns>
- /// <remarks>
- /// The InitializeComponent method generated by the XamlAppDef build task uses a version independent loading strategy for referenced assemblies.
- /// This helper method will ensure that only assemblies provided in the <paramref name="assemblies"/> list will be loaded.
- /// </remarks>
- /// <example>
- /// A overloaded constructor that accepts a <see cref="XamlAssemblyResolutionOption"/>
- /// <code source="Examples\CSDocExamples\WorkflowCompiled.cs" lang="CSharp">
- /// </code>
- /// </example>
- [DebuggerNonUserCode]
- public static bool InitializeComponent<T>(T component, string resourceName, IList<string> assemblies)
- where T : Activity
- {
- var initializeXaml = typeof(T).Assembly.GetManifestResourceStream(resourceName);
-
- if (initializeXaml == null)
- {
- throw new InvalidOperationException("Failed to load XAML from manifest resource stream");
- }
-
- // Gets the schema context with the list of referenced assemblies
- var schemaContext = GetSchemaContext(assemblies);
-
- var readerSettings = new XamlXmlReaderSettings
- {
- LocalAssembly = Assembly.GetExecutingAssembly(),
- AllowProtectedMembersOnRoot = true
- };
- var writerSettings = new XamlObjectWriterSettings
- {
- RootObjectInstance = component,
- AccessLevel = XamlAccessLevel.PrivateAccessTo(typeof(T))
- };
-
- using (var xmlReader = XmlReader.Create(initializeXaml))
- using (var reader = new XamlXmlReader(xmlReader, schemaContext, readerSettings))
- using (var objectWriter = new XamlObjectWriter(schemaContext, writerSettings))
- {
- XamlServices.Transform(reader, objectWriter);
- }
-
- return true;
- }
-
- #endregion
-
- #region Methods
-
- /// <summary>
- /// Gets SchemaContext.
- /// </summary>
- /// <param name="assemblies">
- /// The assemblies.
- /// </param>
- /// <returns>
- /// The schema context.
- /// </returns>
- private static XamlSchemaContext GetSchemaContext(ICollection<string> assemblies = null)
- {
- XamlSchemaContext xsc;
- if (schemaContextField != null)
- {
- xsc = (XamlSchemaContext)schemaContextField.Target;
- if (xsc != null)
- {
- return xsc;
- }
- }
-
- xsc = assemblies != null && assemblies.Count > 0
- ? new XamlSchemaContext(LoadAssemblies(assemblies))
- : new XamlSchemaContext();
-
- schemaContextField = new WeakReference(xsc);
- return xsc;
- }
-
- /// <summary>
- /// Loads a list of assemblies
- /// </summary>
- /// <param name="assemblies">
- /// The assemblies to load.
- /// </param>
- /// <returns>
- /// The list of assemblies loaded
- /// </returns>
- [DebuggerNonUserCode]
- private static IEnumerable<Assembly> LoadAssemblies(IEnumerable<string> assemblies)
- {
- return assemblies == null ? null : assemblies.Select(Assembly.Load).ToList();
- }
-
- #endregion
- }
- }