Added ability to order the execution of dictionary adapter behaviors.
[castle.git] / Components / DictionaryAdapter / Castle.Components.DictionaryAdapter / Attributes / DictionaryStringListAttribute.cs
blobc7ef5c3bd9c63b2cae3d4ca896b7884bae9bf71d
1 // Copyright 2004-2007 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.Components.DictionaryAdapter
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.ComponentModel;
21 using System.Text;
23 /// <summary>
24 /// Identifies a property should be represented as a
25 /// delimited string value.
26 /// </summary>
27 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
28 public class DictionaryStringListAttribute : DictionaryBehaviorAttribute,
29 IDictionaryPropertyGetter,
30 IDictionaryPropertySetter
32 private char separator = ',';
34 /// <summary>
35 /// Gets the separator.
36 /// </summary>
37 public char 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);
77 return storedValue;
80 #endregion
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);
93 return true;
96 #endregion
98 internal static string BuildString(IEnumerable enumerable, char separator)
100 bool first = true;
101 StringBuilder builder = new StringBuilder();
103 foreach(object item in enumerable)
105 if (first)
107 first = false;
109 else
111 builder.Append(separator);
114 builder.Append(item.ToString());
117 return builder.ToString();
121 #region StringList
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)
133 this.key = key;
134 this.separator = separator;
135 this.dictionary = dictionary;
136 inner = new List<T>();
138 ParseList(list);
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();
170 #endregion
172 #region ICollection<T> Members
174 public void Add(T item)
176 inner.Add(item);
177 SynchronizeDictionary();
180 public void Clear()
182 inner.Clear();
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);
196 public int Count
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();
211 return true;
213 return false;
216 #endregion
218 #region IEnumerable<T> Members
220 public IEnumerator<T> GetEnumerator()
222 return inner.GetEnumerator();
225 #endregion
227 #region IEnumerable Members
229 IEnumerator IEnumerable.GetEnumerator()
231 return inner.GetEnumerator();
234 #endregion
236 private void ParseList(string list)
238 if (list != null)
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);
256 #endregion