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
.Components
.DictionaryAdapter
18 using System
.Collections
;
19 using System
.Collections
.Generic
;
20 using System
.ComponentModel
;
24 /// Identifies a property should be represented as a
25 /// delimited string value.
27 [AttributeUsage(AttributeTargets
.Property
, AllowMultiple
= false, Inherited
= true)]
28 public class DictionaryStringListAttribute
: DictionaryBehaviorAttribute
,
29 IDictionaryPropertyGetter
,
30 IDictionaryPropertySetter
32 private char separator
= ',';
35 /// Gets the separator.
39 get { return separator; }
40 set { separator = value; }
43 #region IDictionaryPropertyGetter
45 object IDictionaryPropertyGetter
.GetPropertyValue(
46 IDictionaryAdapterFactory factory
, IDictionary dictionary
,
47 string key
, object storedValue
, PropertyDescriptor property
)
49 Type propertyType
= property
.PropertyType
;
51 if (storedValue
== null ||
52 !storedValue
.GetType().IsInstanceOfType(propertyType
))
54 if (propertyType
.IsGenericType
)
56 Type genericDef
= propertyType
.GetGenericTypeDefinition();
58 if (genericDef
== typeof(IList
<>) ||
59 genericDef
== typeof(ICollection
<>) ||
60 genericDef
== typeof(List
<>) ||
61 genericDef
== typeof(IEnumerable
<>))
63 Type paramType
= propertyType
.GetGenericArguments()[0];
64 TypeConverter converter
= TypeDescriptor
.GetConverter(paramType
);
66 if (converter
!= null && converter
.CanConvertFrom(typeof(string)))
68 Type genericList
= typeof(StringListWrapper
<>).MakeGenericType(
69 new Type
[] {paramType}
);
70 return Activator
.CreateInstance(genericList
, key
, storedValue
,
71 separator
, dictionary
);
82 #region IDictionaryPropertySetter Members
84 bool IDictionaryPropertySetter
.SetPropertyValue(
85 IDictionaryAdapterFactory factory
, IDictionary dictionary
,
86 string key
, ref object value, PropertyDescriptor property
)
88 IEnumerable enumerable
= value as IEnumerable
;
89 if (enumerable
!= null)
91 value = BuildString(enumerable
, separator
);
98 internal static string BuildString(IEnumerable enumerable
, char separator
)
101 StringBuilder builder
= new StringBuilder();
103 foreach(object item
in enumerable
)
111 builder
.Append(separator
);
114 builder
.Append(item
.ToString());
117 return builder
.ToString();
123 internal class StringListWrapper
<T
> : IList
<T
>
125 private readonly string key
;
126 private readonly char separator
;
127 private readonly IDictionary dictionary
;
128 private readonly List
<T
> inner
;
130 public StringListWrapper(string key
, string list
,
131 char separator
, IDictionary dictionary
)
134 this.separator
= separator
;
135 this.dictionary
= dictionary
;
136 inner
= new List
<T
>();
141 #region IList<T> Members
143 public int IndexOf(T item
)
145 return inner
.IndexOf(item
);
148 public void Insert(int index
, T item
)
150 inner
.Insert(index
, item
);
151 SynchronizeDictionary();
154 public void RemoveAt(int index
)
156 inner
.RemoveAt(index
);
157 SynchronizeDictionary();
160 public T
this[int index
]
162 get { return inner[index]; }
165 inner
[index
] = value;
166 SynchronizeDictionary();
172 #region ICollection<T> Members
174 public void Add(T item
)
177 SynchronizeDictionary();
183 SynchronizeDictionary();
186 public bool Contains(T item
)
188 return inner
.Contains(item
);
191 public void CopyTo(T
[] array
, int arrayIndex
)
193 inner
.CopyTo(array
, arrayIndex
);
198 get { return inner.Count; }
201 public bool IsReadOnly
203 get { return false; }
206 public bool Remove(T item
)
208 if (inner
.Remove(item
))
210 SynchronizeDictionary();
218 #region IEnumerable<T> Members
220 public IEnumerator
<T
> GetEnumerator()
222 return inner
.GetEnumerator();
227 #region IEnumerable Members
229 IEnumerator IEnumerable
.GetEnumerator()
231 return inner
.GetEnumerator();
236 private void ParseList(string list
)
240 TypeConverter converter
= TypeDescriptor
.GetConverter(typeof(T
));
242 foreach(string item
in list
.Split(separator
))
244 inner
.Add((T
) converter
.ConvertFrom(item
));
249 private void SynchronizeDictionary()
251 dictionary
[key
] = DictionaryStringListAttribute
.
252 BuildString(inner
, separator
);