1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
.Generic
;
19 using Castle
.Core
.Configuration
;
22 public class GenericDictionaryConverter
: AbstractTypeConverter
25 /// Initializes a new instance of the <see cref="GenericDictionaryConverter"/> class.
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
)
88 public object ConvertConfigurationToCollection(IConfiguration configuration
)
90 Dictionary
<TKey
, TValue
> dict
= new Dictionary
<TKey
, TValue
>();
92 foreach(IConfiguration itemConfig
in configuration
.Children
)
96 String keyValue
= itemConfig
.Attributes
["key"];
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)
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);