Mono exception to SocketException
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Core.Presentation / System / Activities / Core / Presentation / RegisterMetadataDelayedWorker.cs
1 // <copyright>
2 //   Copyright (c) Microsoft Corporation.  All rights reserved.
3 // </copyright>
4
5 namespace System.Activities.Core.Presentation
6 {
7     using System.Activities.Presentation.Metadata;
8     using System.Collections;
9     using System.Collections.Generic;
10     using System.ComponentModel;
11     using System.Reflection;
12     using System.Runtime;
13
14     internal class RegisterMetadataDelayedWorker
15     {
16         private Dictionary<string, List<Action<AttributeTableBuilder>>> delayedWorkItems;
17         private AssemblyLoadEventHandler onAssemblyLoadedEventHandler;
18
19         public Dictionary<string, List<Action<AttributeTableBuilder>>> DelayedWorkItems
20         {
21             get
22             {
23                 if (this.delayedWorkItems == null)
24                 {
25                     this.delayedWorkItems = new Dictionary<string, List<Action<AttributeTableBuilder>>>();
26                 }
27
28                 return this.delayedWorkItems;
29             }
30         }
31
32         public void RegisterMetadataDelayed(string assemblyName, Action<AttributeTableBuilder> delayedWork)
33         {
34             Fx.Assert(assemblyName != null, "Checked by caller");
35             Fx.Assert(delayedWork != null, "Checked by caller");
36             if (this.onAssemblyLoadedEventHandler == null)
37             {
38                 this.onAssemblyLoadedEventHandler = new AssemblyLoadEventHandler(this.OnAssemblyLoaded);
39                 AppDomain.CurrentDomain.AssemblyLoad += this.onAssemblyLoadedEventHandler;
40             }
41
42             List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
43             if (!this.DelayedWorkItems.TryGetValue(assemblyName, out currentDelayedWorkItems))
44             {
45                 currentDelayedWorkItems = new List<Action<AttributeTableBuilder>>();
46                 this.DelayedWorkItems.Add(assemblyName, currentDelayedWorkItems);
47             }
48
49             currentDelayedWorkItems.Add(delayedWork);
50         }
51
52         public void WorkNowIfApplicable()
53         {
54             foreach (Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
55             {
56                 this.CheckAndWork(loadedAssembly);
57             }
58         }
59
60         private void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
61         {
62             try
63             {
64                 this.CheckAndWork(args.LoadedAssembly);
65             }
66             catch
67             {
68                 Fx.AssertAndFailFast("OnAssemblyLoad should not throw exception");
69                 throw;
70             }
71         }
72
73         private void CheckAndWork(Assembly loadedAssembly)
74         {
75             List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
76             if (this.DelayedWorkItems.TryGetValue(loadedAssembly.GetName().Name, out currentDelayedWorkItems))
77             {
78                 Action delayedRegisterMetadataWork = new DelayedRegisterMetadataWorkContext(currentDelayedWorkItems).Work;
79
80                 // Retrieve the top level type descriptor from the stack
81                 TypeDescriptionProvider currentTypeDescriptor = TypeDescriptor.GetProvider(typeof(object));
82
83                 // Intercept any existing changes.
84                 TypeDescriptor.AddProvider(new TypeDescriptionProviderInterceptor(currentTypeDescriptor, delayedRegisterMetadataWork), typeof(object));
85             }
86         }
87
88         private class DelayedRegisterMetadataWorkContext
89         {
90             private List<Action<AttributeTableBuilder>> currentDelayedWorkItems;
91
92             public DelayedRegisterMetadataWorkContext(List<Action<AttributeTableBuilder>> currentDelayedWorkItems)
93             {
94                 this.currentDelayedWorkItems = currentDelayedWorkItems;
95             }
96
97             public void Work()
98             {
99                 AttributeTableBuilder builder = new AttributeTableBuilder();
100                 foreach (Action<AttributeTableBuilder> delayedWork in this.currentDelayedWorkItems)
101                 {
102                     delayedWork(builder);
103                 }
104
105                 MetadataStore.AddSystemAttributeTable(builder.CreateTable());
106             }
107         }
108
109         private class TypeDescriptionProviderInterceptor : TypeDescriptionProvider
110         {
111             private Action interceptingWork;
112
113             public TypeDescriptionProviderInterceptor(TypeDescriptionProvider parent, Action interceptingWork)
114                 : base(parent)
115             {
116                 this.interceptingWork = interceptingWork;
117             }
118
119             public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
120             {
121                 this.PerformInterceptingWork();
122                 return base.CreateInstance(provider, objectType, argTypes, args);
123             }
124
125             public override IDictionary GetCache(object instance)
126             {
127                 this.PerformInterceptingWork();
128                 return base.GetCache(instance);
129             }
130
131             public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
132             {
133                 this.PerformInterceptingWork();
134                 return base.GetExtendedTypeDescriptor(instance);
135             }
136
137             public override string GetFullComponentName(object component)
138             {
139                 this.PerformInterceptingWork();
140                 return base.GetFullComponentName(component);
141             }
142
143             public override Type GetReflectionType(Type objectType, object instance)
144             {
145                 this.PerformInterceptingWork();
146                 return base.GetReflectionType(objectType, instance);
147             }
148
149             public override Type GetRuntimeType(Type reflectionType)
150             {
151                 this.PerformInterceptingWork();
152                 return base.GetRuntimeType(reflectionType);
153             }
154
155             public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
156             {
157                 this.PerformInterceptingWork();
158                 return base.GetTypeDescriptor(objectType, instance);
159             }
160
161             public override bool IsSupportedType(Type type)
162             {
163                 this.PerformInterceptingWork();
164                 return base.IsSupportedType(type);
165             }
166
167             private void PerformInterceptingWork()
168             {
169                 // Make sure the intercepting work is done only once.
170                 TypeDescriptor.RemoveProvider(this, typeof(object));
171                 if (this.interceptingWork != null)
172                 {
173                     this.interceptingWork();
174                     this.interceptingWork = null;
175                 }
176             }
177         }
178     }
179 }