285b990d718aaa1f93fd86c09a4de52e8e209cfe
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Model / XamlUtilities.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5
6 namespace System.Activities.Presentation.Model
7 {
8
9     using System;
10     using System.Collections;
11     using System.ComponentModel;
12     using System.Reflection;
13
14
15     internal static class XamlUtilities
16     {
17
18         static Hashtable converterCache;
19         static object converterCacheSyncObject = new object();
20
21         public static TypeConverter GetConverter(Type itemType)
22         {
23             TypeConverter converter = TypeDescriptor.GetConverter(itemType);
24
25             if (converter == null || converter.GetType() == typeof(TypeConverter))
26             {
27
28                 // We got an invalid converter.  WPF will do this if the converter
29                 // is internal, but we use internal converters all over the place
30                 // at design time.  Detect this and build the converter ourselves.
31
32                 if (converterCache != null)
33                 {
34                     converter = (TypeConverter)converterCache[itemType];
35                     if (converter != null)
36                     {
37                         return converter;
38                     }
39                 }
40
41                 AttributeCollection attrs = TypeDescriptor.GetAttributes(itemType);
42                 TypeConverterAttribute tca = attrs[typeof(TypeConverterAttribute)] as TypeConverterAttribute;
43                 if (tca != null && tca.ConverterTypeName != null)
44                 {
45                     Type type = Type.GetType(tca.ConverterTypeName);
46                     if (type != null && !type.IsPublic && typeof(TypeConverter).IsAssignableFrom(type))
47                     {
48                         ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(Type) });
49                         if (ctor != null)
50                         {
51                             converter = (TypeConverter)ctor.Invoke(new object[] { itemType });
52                         }
53                         else
54                         {
55                             converter = (TypeConverter)Activator.CreateInstance(type);
56                         }
57
58                         lock (converterCacheSyncObject)
59                         {
60                             if (converterCache == null)
61                             {
62                                 converterCache = new Hashtable();
63
64                                 // Listen to type changes and clear the cache.
65                                 // This allows new metadata tables to be installed
66
67                                 TypeDescriptor.Refreshed += delegate(RefreshEventArgs args)
68                                 {
69                                     converterCache.Remove(args.TypeChanged);
70                                 };
71                             }
72
73                             converterCache[itemType] = converter;
74                         }
75                     }
76                 }
77             }
78
79             return converter;
80         }
81     }
82 }