2 // Copyright (c) Microsoft Corporation. All rights reserved.
5 namespace System.Activities.Core.Presentation
7 using System.Activities.Presentation.Metadata;
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.ComponentModel;
11 using System.Reflection;
14 internal class RegisterMetadataDelayedWorker
16 private Dictionary<string, List<Action<AttributeTableBuilder>>> delayedWorkItems;
17 private AssemblyLoadEventHandler onAssemblyLoadedEventHandler;
19 public Dictionary<string, List<Action<AttributeTableBuilder>>> DelayedWorkItems
23 if (this.delayedWorkItems == null)
25 this.delayedWorkItems = new Dictionary<string, List<Action<AttributeTableBuilder>>>();
28 return this.delayedWorkItems;
32 public void RegisterMetadataDelayed(string assemblyName, Action<AttributeTableBuilder> delayedWork)
34 Fx.Assert(assemblyName != null, "Checked by caller");
35 Fx.Assert(delayedWork != null, "Checked by caller");
36 if (this.onAssemblyLoadedEventHandler == null)
38 this.onAssemblyLoadedEventHandler = new AssemblyLoadEventHandler(this.OnAssemblyLoaded);
39 AppDomain.CurrentDomain.AssemblyLoad += this.onAssemblyLoadedEventHandler;
42 List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
43 if (!this.DelayedWorkItems.TryGetValue(assemblyName, out currentDelayedWorkItems))
45 currentDelayedWorkItems = new List<Action<AttributeTableBuilder>>();
46 this.DelayedWorkItems.Add(assemblyName, currentDelayedWorkItems);
49 currentDelayedWorkItems.Add(delayedWork);
52 public void WorkNowIfApplicable()
54 foreach (Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
56 this.CheckAndWork(loadedAssembly);
60 private void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
64 this.CheckAndWork(args.LoadedAssembly);
68 Fx.AssertAndFailFast("OnAssemblyLoad should not throw exception");
73 private void CheckAndWork(Assembly loadedAssembly)
75 List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
76 if (this.DelayedWorkItems.TryGetValue(loadedAssembly.GetName().Name, out currentDelayedWorkItems))
78 Action delayedRegisterMetadataWork = new DelayedRegisterMetadataWorkContext(currentDelayedWorkItems).Work;
80 // Retrieve the top level type descriptor from the stack
81 TypeDescriptionProvider currentTypeDescriptor = TypeDescriptor.GetProvider(typeof(object));
83 // Intercept any existing changes.
84 TypeDescriptor.AddProvider(new TypeDescriptionProviderInterceptor(currentTypeDescriptor, delayedRegisterMetadataWork), typeof(object));
88 private class DelayedRegisterMetadataWorkContext
90 private List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
92 public DelayedRegisterMetadataWorkContext(List<Action<AttributeTableBuilder>> currentDelayedWorkItems)
94 this.currentDelayedWorkItems = currentDelayedWorkItems;
99 AttributeTableBuilder builder = new AttributeTableBuilder();
100 foreach (Action<AttributeTableBuilder> delayedWork in this.currentDelayedWorkItems)
102 delayedWork(builder);
105 MetadataStore.AddSystemAttributeTable(builder.CreateTable());
109 private class TypeDescriptionProviderInterceptor : TypeDescriptionProvider
111 private Action interceptingWork;
113 public TypeDescriptionProviderInterceptor(TypeDescriptionProvider parent, Action interceptingWork)
116 this.interceptingWork = interceptingWork;
119 public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
121 this.PerformInterceptingWork();
122 return base.CreateInstance(provider, objectType, argTypes, args);
125 public override IDictionary GetCache(object instance)
127 this.PerformInterceptingWork();
128 return base.GetCache(instance);
131 public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
133 this.PerformInterceptingWork();
134 return base.GetExtendedTypeDescriptor(instance);
137 public override string GetFullComponentName(object component)
139 this.PerformInterceptingWork();
140 return base.GetFullComponentName(component);
143 public override Type GetReflectionType(Type objectType, object instance)
145 this.PerformInterceptingWork();
146 return base.GetReflectionType(objectType, instance);
149 public override Type GetRuntimeType(Type reflectionType)
151 this.PerformInterceptingWork();
152 return base.GetRuntimeType(reflectionType);
155 public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
157 this.PerformInterceptingWork();
158 return base.GetTypeDescriptor(objectType, instance);
161 public override bool IsSupportedType(Type type)
163 this.PerformInterceptingWork();
164 return base.IsSupportedType(type);
167 private void PerformInterceptingWork()
169 // Make sure the intercepting work is done only once.
170 TypeDescriptor.RemoveProvider(this, typeof(object));
171 if (this.interceptingWork != null)
173 this.interceptingWork();
174 this.interceptingWork = null;