2 // Copyright (c) Microsoft Corporation. All rights reserved.
5 namespace Microsoft.Activities.Presentation.Xaml
8 using System.Activities.Presentation;
9 using System.Activities.Presentation.Hosting;
10 using System.Activities.Presentation.Xaml;
11 using System.Collections.Generic;
12 using System.ComponentModel;
13 using System.ComponentModel.Composition;
14 using System.Diagnostics.CodeAnalysis;
16 using System.Reflection;
17 using System.Runtime.CompilerServices;
18 using System.Runtime.Versioning;
20 using Microsoft.Activities.Presentation;
22 class WorkflowDesignerXamlSchemaContext : XamlSchemaContext
24 //post fix for xml namespace defined by CLR namespace in local assembly
25 readonly string localAssemblyNsPostfix;
26 readonly string localAssemblyNsPostfixNoLeadingSemicolon;
27 // Cache of custom XamlTypes
28 Dictionary<Type, XamlType> customXamlTypes;
29 EditingContext editingContext;
30 bool environmentAssembliesLoaded;
31 private readonly static FrameworkName CurrentFramework = FrameworkNameConstants.NetFramework45;
32 private ResolverCache resolverCache;
34 private static List<Type> supportedTypes;
35 private static List<Type> conversionRequiredTypes;
37 [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
38 static WorkflowDesignerXamlSchemaContext()
40 supportedTypes = new List<Type>();
41 supportedTypes.Add(typeof(System.Activities.Presentation.Expressions.ExpressionActivityEditor));
42 supportedTypes.Add(typeof(System.Activities.Presentation.Annotations.Annotation));
44 conversionRequiredTypes = new List<Type>();
45 conversionRequiredTypes.Add(typeof(System.Activities.Expressions.TextExpression));
46 conversionRequiredTypes.Add(typeof(System.Activities.Expressions.AssemblyReference));
47 conversionRequiredTypes.Add(typeof(System.Collections.ObjectModel.Collection<System.Activities.Expressions.AssemblyReference>));
48 conversionRequiredTypes.Add(typeof(System.Activities.Debugger.Symbol.DebugSymbol));
49 conversionRequiredTypes.Add(typeof(System.Activities.Presentation.ViewState.WorkflowViewState));
50 conversionRequiredTypes.Add(typeof(System.Activities.Presentation.ViewState.ViewStateManager));
51 conversionRequiredTypes.Add(typeof(System.Activities.Presentation.ViewState.ViewStateData));
54 public WorkflowDesignerXamlSchemaContext(string localAssembly) : this(localAssembly, null)
58 public WorkflowDesignerXamlSchemaContext(string localAssembly, EditingContext editingContext)
60 if (!string.IsNullOrEmpty(localAssembly))
62 this.localAssemblyNsPostfix = XamlNamespaceHelper.ClrNamespaceAssemblyField + localAssembly;
63 this.localAssemblyNsPostfixNoLeadingSemicolon = localAssemblyNsPostfix.Substring(1);
65 this.editingContext = editingContext;
68 internal bool ContainsConversionRequiredType { get; set; }
70 protected override XamlType GetXamlType(string xamlNamespace, string name, params XamlType[] typeArguments)
72 if (!string.IsNullOrEmpty(this.localAssemblyNsPostfix)
73 && IsClrNamespaceWithNoAssembly(xamlNamespace))
75 xamlNamespace = AddLocalAssembly(xamlNamespace);
78 var xamlType = base.GetXamlType(xamlNamespace, name, typeArguments);
80 if (xamlType == null && environmentAssembliesLoaded == false && editingContext != null)
82 // Failed to find the type, this might because the namespace is a custom namespace
83 // and the dependent assembly hasn't been loaded yet. Load all dependent assemblies
84 // and try to load the same xaml type again.
85 AssemblyContextControlItem assemblyItem = this.editingContext.Items.GetValue<AssemblyContextControlItem>();
86 var environmentAssemblies = assemblyItem.GetEnvironmentAssemblies(null);
87 if (assemblyItem.LocalAssemblyName != null)
89 AssemblyContextControlItem.GetAssembly(assemblyItem.LocalAssemblyName, null);
92 environmentAssembliesLoaded = true;
93 xamlType = base.GetXamlType(xamlNamespace, name, typeArguments);
96 if (xamlType == null || xamlType.UnderlyingType == null || this.editingContext == null)
101 MultiTargetingSupportService multiTargetingService = editingContext.Services.GetService<IMultiTargetingSupportService>() as MultiTargetingSupportService;
102 DesignerConfigurationService config = editingContext.Services.GetService<DesignerConfigurationService>();
103 if (multiTargetingService == null || config == null)
108 // do not filter out new types and new properties if targeting to current framework and it's a full SKU
109 if (config.TargetFrameworkName.Version == CurrentFramework.Version && config.TargetFrameworkName.IsFullProfile())
114 // Filter out new types and new properties
115 if (this.resolverCache == null)
117 this.resolverCache = new ResolverCache();
120 if (supportedTypes.Contains(xamlType.UnderlyingType))
125 // only check if conversion is needed when target framework is less than 4.5
126 if (config.TargetFrameworkName.Version < CurrentFramework.Version)
128 if (conversionRequiredTypes.Contains(xamlType.UnderlyingType))
130 this.ContainsConversionRequiredType = true;
135 ResolverResult resolverResult = this.resolverCache.Lookup(xamlType.UnderlyingType);
136 if (resolverResult == null)
138 resolverResult = MultiTargetingTypeResolver.Resolve(multiTargetingService, xamlType.UnderlyingType);
139 this.resolverCache.Update(xamlType.UnderlyingType, resolverResult);
142 return MultiTargetingTypeResolver.GetXamlType(resolverResult, xamlType);
145 public override XamlType GetXamlType(Type type)
147 XamlType xamlType = null;
148 if (this.customXamlTypes != null && this.customXamlTypes.TryGetValue(type, out xamlType))
152 bool isCustom = false;
153 xamlType = GetCustomType(type);
154 if (xamlType != null)
160 xamlType = base.GetXamlType(type);
161 if (xamlType.GetXamlNamespaces().Any(ns => IsClrNamespaceInLocalAssembly(ns)))
164 xamlType = new XamlTypeWithExplicitNamespace(xamlType, xamlType.GetXamlNamespaces().Select(ns => IsClrNamespaceInLocalAssembly(ns) ? TrimLocalAssembly(ns) : ns));
169 if (this.customXamlTypes == null)
171 this.customXamlTypes = new Dictionary<Type, XamlType>();
173 this.customXamlTypes[type] = xamlType;
178 public override IEnumerable<string> GetAllXamlNamespaces()
180 foreach (string ns in base.GetAllXamlNamespaces())
182 if (IsClrNamespaceInLocalAssembly(ns))
184 yield return TrimLocalAssembly(ns);
193 internal bool HasLocalAssembly
195 get { return !string.IsNullOrEmpty(this.localAssemblyNsPostfix); }
198 internal string AddLocalAssembly(string ns)
201 // clr-namespace:X.Y.Z ==> clr-namespace:X.Y.Z;assembly=MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
202 if (result[result.Length - 1] != ';')
204 result += this.localAssemblyNsPostfix;
208 result += this.localAssemblyNsPostfixNoLeadingSemicolon;
213 internal bool IsClrNamespaceWithNoAssembly(string ns)
215 //could be more sophisticated with a RegEx, but let's keep it simple for now
216 return ns.StartsWith(XamlNamespaceHelper.ClrNamespacePrefix, StringComparison.OrdinalIgnoreCase) &&
217 ns.IndexOf(XamlNamespaceHelper.ClrNamespaceAssemblyField, StringComparison.OrdinalIgnoreCase) == -1;
220 internal bool IsClrNamespaceInLocalAssembly(string ns)
222 //could be more sophisticated with a RegEx, but let's keep it simple for now
224 return !string.IsNullOrEmpty(this.localAssemblyNsPostfix) && ns.EndsWith(this.localAssemblyNsPostfix, StringComparison.OrdinalIgnoreCase);
227 internal string TrimLocalAssembly(string ns)
229 return string.IsNullOrEmpty(this.localAssemblyNsPostfix) ? ns : ns.Substring(0, ns.Length - this.localAssemblyNsPostfix.Length);
232 XamlType GetCustomType(Type type)
234 if (type == typeof(DesignerAttribute))
236 return new AttributeXamlType<DesignerAttribute, DesignerAttributeInfo>(this);
238 if (type == typeof(EditorAttribute))
240 return new AttributeXamlType<EditorAttribute, EditorAttributeInfo>(this);
242 if (type == typeof(DefaultValueAttribute))
244 return new AttributeXamlType<DefaultValueAttribute, DefaultValueAttributeInfo>(this);
246 if (type.Namespace == "System.ComponentModel.Composition")
248 return GetCustomMefType(type);
250 #if ERROR_TOLERANT_SUPPORT
251 if (ErrorTolerantObjectWriter.IsErrorActivity(type))
253 return new ShimAsPublicXamlType(type, this);
259 // Avoid loading System.ComponentModel.Composition unless we need it
260 [MethodImpl(MethodImplOptions.NoInlining)]
261 XamlType GetCustomMefType(Type type)
263 if (type == typeof(ImportAttribute))
265 return new AttributeXamlType<ImportAttribute, ImportAttributeInfo>(this);
267 if (type == typeof(ImportManyAttribute))
269 return new AttributeXamlType<ImportAttribute, ImportAttributeInfo>(this);