Removed untyped contructor from ComponentRegistration and add a protected setter.
[castle.git] / InversionOfControl / Castle.MicroKernel / SubSystems / Conversion / Converters / Generics / GenericDictionaryConverter.cs
blobe1433536cb65369884b57705c665dd5ca91fe484
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MicroKernel.SubSystems.Conversion
17 using System;
18 using System.Collections.Generic;
19 using Castle.Core.Configuration;
21 [Serializable]
22 public class GenericDictionaryConverter : AbstractTypeConverter
24 /// <summary>
25 /// Initializes a new instance of the <see cref="GenericDictionaryConverter"/> class.
26 /// </summary>
27 public GenericDictionaryConverter()
31 public override bool CanHandleType(Type type)
33 if (!type.IsGenericType) return false;
35 Type genericDef = type.GetGenericTypeDefinition();
37 return (genericDef == typeof(IDictionary<,>) || genericDef == typeof(Dictionary<,>));
40 public override object PerformConversion(String value, Type targetType)
42 throw new NotImplementedException();
45 public override object PerformConversion(IConfiguration configuration, Type targetType)
47 System.Diagnostics.Debug.Assert(CanHandleType(targetType), "Got a type we can't handle!");
49 Type[] argTypes = targetType.GetGenericArguments();
51 if (argTypes.Length != 2)
53 throw new ConverterException("Expected type with two generic arguments.");
56 String keyTypeName = configuration.Attributes["keyType"];
57 Type defaultKeyType = argTypes[0];
59 String valueTypeName = configuration.Attributes["valueType"];
60 Type defaultValueType = argTypes[1];
62 if (keyTypeName != null)
64 defaultKeyType = (Type) Context.Composition.PerformConversion(keyTypeName, typeof(Type));
67 if (valueTypeName != null)
69 defaultValueType = (Type) Context.Composition.PerformConversion(valueTypeName, typeof(Type));
72 IGenericCollectionConverterHelper collectionConverterHelper =
73 (IGenericCollectionConverterHelper)
74 Activator.CreateInstance(typeof(DictionaryHelper<,>).MakeGenericType(defaultKeyType, defaultValueType), this);
76 return collectionConverterHelper.ConvertConfigurationToCollection(configuration);
79 private class DictionaryHelper<TKey, TValue> : IGenericCollectionConverterHelper
81 private GenericDictionaryConverter parent;
83 public DictionaryHelper(GenericDictionaryConverter parent)
85 this.parent = parent;
88 public object ConvertConfigurationToCollection(IConfiguration configuration)
90 Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
92 foreach(IConfiguration itemConfig in configuration.Children)
94 // Preparing the key
96 String keyValue = itemConfig.Attributes["key"];
98 if (keyValue == null)
100 throw new ConverterException("You must provide a key for the dictionary entry");
103 Type convertKeyTo = typeof(TKey);
105 if (itemConfig.Attributes["keyType"] != null)
107 convertKeyTo = (Type) parent.Context.Composition.PerformConversion(itemConfig.Attributes["keyType"], typeof(Type));
110 if (!typeof(TKey).IsAssignableFrom(convertKeyTo))
112 throw new ArgumentException(
113 string.Format("Could not create dictionary<{0},{1}> because {2} is not assignmable to key type {0}", typeof(TKey),
114 typeof(TValue), convertKeyTo));
117 TKey key = (TKey) parent.Context.Composition.PerformConversion(keyValue, convertKeyTo);
119 // Preparing the value
121 Type convertValueTo = typeof(TValue);
123 if (itemConfig.Attributes["valueType"] != null)
125 convertValueTo =
126 (Type) parent.Context.Composition.PerformConversion(itemConfig.Attributes["valueType"], typeof(Type));
129 if (!typeof(TValue).IsAssignableFrom(convertValueTo))
131 throw new ArgumentException(
132 string.Format("Could not create dictionary<{0},{1}> because {2} is not assignmable to value type {1}",
133 typeof(TKey), typeof(TValue), convertValueTo));
135 TValue value = (TValue) parent.Context.Composition.PerformConversion(itemConfig.Value, convertValueTo);
137 dict.Add(key, value);
139 return dict;