diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Castle.Core.csproj nmock3-62490\MAIN\Source\Castle\Castle.Core.csproj
--- nmock3-62490-original\MAIN\Source\Castle\Castle.Core.csproj Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Castle.Core.csproj Sun Feb 13 18:56:53 2011
@@ -0,0 +1,629 @@
+
+
+
+ $(MSBuildProjectDirectory)\..\..
+ v4.0
+ Client
+
+
+ NET40-Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {E4FA5B53-7D36-429E-8E5C-53D5479242BA}
+ Library
+ Properties
+ Castle
+ Castle.Core
+ true
+ ..\..\buildscripts\CastleKey.snk
+
+
+
+
+ v4.0
+ Client
+ bin\NET40-Debug\
+ true
+ full
+ false
+ TRACE;DEBUG;PHYSICALASSEMBLY DOTNET DOTNET40 CLIENTPROFILE
+ prompt
+ 4
+ true
+
+
+ 1591
+ true
+
+
+ v4.0
+ Client
+ bin\NET40-Release\
+ pdbonly
+ true
+ TRACE;PHYSICALASSEMBLY DOTNET DOTNET40 CLIENTPROFILE
+ prompt
+ 4
+ bin\NET40-Release\Castle.Core.xml
+ 1591
+ true
+
+
+ v3.5
+
+
+ bin\NET35-Debug\
+ TRACE;DEBUG;PHYSICALASSEMBLY DOTNET DOTNET35
+
+
+ true
+ true
+ 1591
+ pdbonly
+ AnyCPU
+ prompt
+ true
+
+
+ v3.5
+
+
+ bin\NET35-Release\
+ TRACE;PHYSICALASSEMBLY DOTNET DOTNET35
+ bin\NET35-Release\Castle.Core.xml
+ true
+ true
+ 1591
+ pdbonly
+ AnyCPU
+ prompt
+
+
+ v4.0
+
+
+ Silverlight 4.0
+ bin\SL40-Release\
+ TRACE;PHYSICALASSEMBLY SILVERLIGHT SL4
+ bin\SL40-Release\Castle.Core.xml
+ true
+ true
+ 1591 1685
+ pdbonly
+ AnyCPU
+ prompt
+
+
+ v4.0
+
+
+ Silverlight 4.0
+ true
+ bin\SL40-Debug\
+ TRACE;DEBUG;PHYSICALASSEMBLY SILVERLIGHT SL4
+
+
+ true
+ 1591 1685
+ full
+ AnyCPU
+ prompt
+
+
+
+
+ true
+ bin\SL30-Debug\
+ TRACE;DEBUG;PHYSICALASSEMBLY SILVERLIGHT SL3
+
+
+ true
+ 1591 1685
+ full
+ AnyCPU
+ prompt
+
+
+
+
+ bin\SL30-Release\
+ TRACE;PHYSICALASSEMBLY SILVERLIGHT SL3
+ bin\SL30-Release\Castle.Core.xml
+ true
+ true
+ 1591 1685
+ pdbonly
+ AnyCPU
+ prompt
+
+
+
+
+ bin\MONO26-Debug\
+ TRACE;DEBUG;PHYSICALASSEMBLY MONO MONO26
+ bin\MONO26-Debug\Castle.Core.xml
+ false
+ full
+ true
+ 1591
+ AnyCPU
+ prompt
+ true
+
+
+
+
+ bin\MONO26-Release\
+ TRACE;PHYSICALASSEMBLY MONO MONO26
+ bin\MONO26-Release\Castle.Core.xml
+ true
+ pdbonly
+ true
+ 1591
+ AnyCPU
+
+
+
+
+ bin\MONO28-Debug\
+ TRACE;DEBUG;PHYSICALASSEMBLY MONO MONO28
+ bin\MONO28-Debug\Castle.Core.xml
+ false
+ full
+ true
+ 1591
+ AnyCPU
+ prompt
+ true
+
+
+
+
+ bin\MONO28-Release\
+ TRACE;PHYSICALASSEMBLY MONO MONO28
+ bin\MONO28-Release\Castle.Core.xml
+ true
+ pdbonly
+ true
+ 1591
+ AnyCPU
+
+
+
+
+
+
+
+
+
+
+
+ CommonAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CastleKey.snk
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapter.cs Sun Feb 13 19:16:30 2011
@@ -0,0 +1,178 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License";
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Abstract adapter for the support
+ /// needed by the
+ ///
+ internal abstract class AbstractDictionaryAdapter : IDictionary
+ {
+ ///
+ /// Adds an element with the provided key and value to the object.
+ ///
+ /// The to use as the key of the element to add.
+ /// The to use as the value of the element to add.
+ /// An element with the same key already exists in the object.
+ /// key is null.
+ /// The is read-only.-or- The has a fixed size.
+ public void Add(object key, object value)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Removes all elements from the object.
+ ///
+ /// The object is read-only.
+ public void Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Determines whether the object contains an element with the specified key.
+ ///
+ /// The key to locate in the object.
+ ///
+ /// true if the contains an element with the key; otherwise, false.
+ ///
+ /// key is null.
+ public abstract bool Contains(object key);
+
+ ///
+ /// Returns an object for the object.
+ ///
+ ///
+ /// An object for the object.
+ ///
+ public IDictionaryEnumerator GetEnumerator()
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Gets a value indicating whether the object has a fixed size.
+ ///
+ ///
+ /// true if the object has a fixed size; otherwise, false.
+ public bool IsFixedSize
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// Gets a value indicating whether the object is read-only.
+ ///
+ ///
+ /// true if the object is read-only; otherwise, false.
+ public abstract bool IsReadOnly { get; }
+
+ ///
+ /// Gets an object containing the keys of the object.
+ ///
+ ///
+ /// An object containing the keys of the object.
+ public ICollection Keys
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// Removes the element with the specified key from the object.
+ ///
+ /// The key of the element to remove.
+ /// The object is read-only.-or- The has a fixed size.
+ /// key is null.
+ public void Remove(object key)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Gets an object containing the values in the object.
+ ///
+ ///
+ /// An object containing the values in the object.
+ public ICollection Values
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// Gets or sets the with the specified key.
+ ///
+ ///
+ public abstract object this[object key] { get; set; }
+
+ ///
+ /// Copies the elements of the to an , starting at a particular index.
+ ///
+ /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
+ /// The zero-based index in array at which copying begins.
+ /// array is null.
+ /// The type of the source cannot be cast automatically to the type of the destination array.
+ /// index is less than zero.
+ /// array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source is greater than the available space from index to the end of the destination array.
+ public void CopyTo(Array array, int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Gets the number of elements contained in the .
+ ///
+ ///
+ /// The number of elements contained in the .
+ public int Count
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// Gets a value indicating whether access to the is synchronized (thread safe).
+ ///
+ ///
+ /// true if access to the is synchronized (thread safe); otherwise, false.
+ public virtual bool IsSynchronized
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Gets an object that can be used to synchronize access to the .
+ ///
+ ///
+ /// An object that can be used to synchronize access to the .
+ public virtual object SyncRoot
+ {
+ get { return this; }
+ }
+
+ ///
+ /// Returns an enumerator that iterates through a collection.
+ ///
+ ///
+ /// An object that can be used to iterate through the collection.
+ ///
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapterVisitor.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapterVisitor.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapterVisitor.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\AbstractDictionaryAdapterVisitor.cs Sun Feb 13 19:16:35 2011
@@ -0,0 +1,100 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Abstract implementation of .
+ ///
+ internal abstract class AbstractDictionaryAdapterVisitor : IDictionaryAdapterVisitor
+ {
+ public virtual void VisitDictionaryAdapter(IDictionaryAdapter dictionaryAdapter)
+ {
+ foreach (var property in dictionaryAdapter.This.Properties.Values)
+ {
+ Type collectionItemType;
+ if (IsCollection(property, out collectionItemType))
+ {
+ VisitCollection(dictionaryAdapter, property, collectionItemType);
+ }
+ else if (property.PropertyType.IsInterface)
+ {
+ VisitInterface(dictionaryAdapter, property);
+ }
+ else
+ {
+ VisitProperty(dictionaryAdapter, property);
+ }
+ }
+ }
+
+ void IDictionaryAdapterVisitor.VisitProperty(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property)
+ {
+ VisitProperty(dictionaryAdapter, property);
+ }
+
+ protected virtual void VisitProperty(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property)
+ {
+ }
+
+ void IDictionaryAdapterVisitor.VisitInterface(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property)
+ {
+ VisitInterface(dictionaryAdapter, property);
+ }
+
+ protected virtual void VisitInterface(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property)
+ {
+
+ }
+
+ void IDictionaryAdapterVisitor.VisitCollection(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property,
+ Type collectionItemType)
+ {
+ VisitCollection(dictionaryAdapter, property, collectionItemType);
+ }
+
+ protected virtual void VisitCollection(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property,
+ Type collectionItemType)
+ {
+ VisitProperty(dictionaryAdapter, property);
+ }
+
+ private static bool IsCollection(PropertyDescriptor property, out Type collectionItemType)
+ {
+ collectionItemType = null;
+ var propertyType = property.PropertyType;
+ if (propertyType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(propertyType))
+ {
+ if (propertyType.IsArray)
+ {
+ collectionItemType = propertyType.GetElementType();
+ }
+ else if (propertyType.IsGenericType)
+ {
+ var arguments = propertyType.GetGenericArguments();
+ collectionItemType = arguments[0];
+ }
+ else
+ {
+ collectionItemType = typeof(object);
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\ComponentAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\ComponentAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\ComponentAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\ComponentAttribute.cs Sun Feb 13 19:33:00 2011
@@ -0,0 +1,94 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Identifies a property should be represented as a nested component.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ internal class ComponentAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder,
+ IDictionaryPropertyGetter, IDictionaryPropertySetter
+ {
+ ///
+ /// Applies no prefix.
+ ///
+ public bool NoPrefix
+ {
+ get { return Prefix == ""; }
+ set
+ {
+ if (value)
+ {
+ Prefix = "";
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the prefix.
+ ///
+ /// The prefix.
+ public string Prefix { get; set; }
+
+ #region IDictionaryKeyBuilder Members
+
+ string IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, string key,
+ PropertyDescriptor property)
+ {
+ return Prefix ?? key + "_";
+ }
+
+ #endregion
+
+ #region IDictionaryPropertyGetter
+
+ object IDictionaryPropertyGetter.GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ if (storedValue == null)
+ {
+ var component = dictionaryAdapter.This.ExtendedProperties[property.PropertyName];
+
+ if (component == null)
+ {
+ var descriptor = new PropertyDescriptor(property.Property, null);
+ descriptor.AddKeyBuilder(new KeyPrefixAttribute(key));
+ component = dictionaryAdapter.This.Factory.GetAdapter(
+ property.Property.PropertyType, dictionaryAdapter.This.Dictionary, descriptor);
+ dictionaryAdapter.This.ExtendedProperties[property.PropertyName] = component;
+ }
+
+ return component;
+ }
+
+ return storedValue;
+ }
+
+ #endregion
+
+ #region IDictionaryPropertySetter Members
+
+ public bool SetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, ref object value, PropertyDescriptor property)
+ {
+ dictionaryAdapter.This.ExtendedProperties.Remove(property.PropertyName);
+ return true;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryAdapterAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryAdapterAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryAdapterAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryAdapterAttribute.cs Sun Feb 13 19:33:06 2011
@@ -0,0 +1,32 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Identifies the dictionary adapter types.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ internal class DictionaryAdapterAttribute : Attribute
+ {
+ public DictionaryAdapterAttribute(Type interfaceType)
+ {
+ InterfaceType = interfaceType;
+ }
+
+ public Type InterfaceType { get; private set; }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryBehaviorAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryBehaviorAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryBehaviorAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\DictionaryBehaviorAttribute.cs Sun Feb 13 19:33:11 2011
@@ -0,0 +1,38 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Assignes a specific dictionary key.
+ ///
+ internal abstract class DictionaryBehaviorAttribute : Attribute, IDictionaryBehavior
+ {
+ public const int FiratExecutionOrder = 0;
+ public const int DefaultExecutionOrder = int.MaxValue / 2;
+ public const int LastExecutionOrder = int.MaxValue;
+
+ public DictionaryBehaviorAttribute()
+ {
+ ExecutionOrder = DefaultExecutionOrder;
+ }
+
+ ///
+ /// Determines relative order to apply related behaviors.
+ ///
+ public int ExecutionOrder { get; set; }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\FetchAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\FetchAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\FetchAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\FetchAttribute.cs Sun Feb 13 19:33:19 2011
@@ -0,0 +1,46 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Identifies an interface or property to be pre-feteched.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = false)]
+ internal class FetchAttribute : Attribute
+ {
+ ///
+ /// Instructs fetching to occur.
+ ///
+ public FetchAttribute() : this(true)
+ {
+ }
+
+ ///
+ /// Instructs fetching according to
+ ///
+ ///
+ public FetchAttribute(bool fetch)
+ {
+ Fetch = fetch;
+ }
+
+ ///
+ /// Gets whether or not fetching should occur.
+ ///
+ public bool Fetch { get; private set; }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\GroupAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\GroupAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\GroupAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\GroupAttribute.cs Sun Feb 13 19:33:25 2011
@@ -0,0 +1,48 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Assigns a property to a group.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
+ internal class GroupAttribute : Attribute
+ {
+ ///
+ /// Constructs a group assignment.
+ ///
+ /// The group name.
+ public GroupAttribute(object group)
+ {
+ Group = new [] { group };
+ }
+
+ ///
+ /// Constructs a group assignment.
+ ///
+ /// The group name.
+ public GroupAttribute(params object[] group)
+ {
+ Group = group;
+ }
+
+ ///
+ /// Gets the group the property is assigned to.
+ ///
+ public object[] Group { get; private set; }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyAttribute.cs Sun Feb 13 19:33:30 2011
@@ -0,0 +1,52 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Assigns a specific dictionary key.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ internal class KeyAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
+ {
+ private readonly String key;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ public KeyAttribute(String key)
+ {
+ this.key = key;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The compound key.
+ public KeyAttribute(String[] keys)
+ {
+ this.key = string.Join(",", keys);
+ }
+
+ public String Key { get; private set; }
+ String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property)
+ {
+ return this.key;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyPrefixAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyPrefixAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyPrefixAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeyPrefixAttribute.cs Sun Feb 13 19:33:34 2011
@@ -0,0 +1,58 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Assigns a prefix to the keyed properties of an interface.
+ ///
+ [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
+ internal class KeyPrefixAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
+ {
+ private String keyPrefix;
+
+ ///
+ /// Initializes a default instance of the class.
+ ///
+ public KeyPrefixAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The prefix for the keyed properties of the interface.
+ public KeyPrefixAttribute(String keyPrefix)
+ {
+ this.keyPrefix = keyPrefix;
+ }
+
+ ///
+ /// Gets the prefix key added to the properties of the interface.
+ ///
+ public String KeyPrefix
+ {
+ get { return keyPrefix; }
+ set { keyPrefix = value; }
+ }
+
+ String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property)
+ {
+ return keyPrefix + key;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeySubstitutionAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeySubstitutionAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeySubstitutionAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\KeySubstitutionAttribute.cs Sun Feb 13 19:33:40 2011
@@ -0,0 +1,44 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Substitutes part of key with another string.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
+ internal class KeySubstitutionAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
+ {
+ private readonly String oldValue;
+ private readonly String newValue;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old value.
+ /// The new value.
+ public KeySubstitutionAttribute(String oldValue, String newValue)
+ {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property)
+ {
+ return key.Replace(oldValue, newValue);
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\MultiLevelEditAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\MultiLevelEditAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\MultiLevelEditAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\MultiLevelEditAttribute.cs Sun Feb 13 19:33:45 2011
@@ -0,0 +1,30 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Requests support for multi-level editing.
+ ///
+ [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false)]
+ internal class MultiLevelEditAttribute : DictionaryBehaviorAttribute, IDictionaryInitializer
+ {
+ public void Initialize(IDictionaryAdapter dictionaryAdapter, object[] behaviors)
+ {
+ dictionaryAdapter.SupportsMultiLevelEdit = true;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\NewGuidAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\NewGuidAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\NewGuidAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\NewGuidAttribute.cs Sun Feb 13 19:33:50 2011
@@ -0,0 +1,40 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Generates a new GUID on demand.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = false)]
+ internal class NewGuidAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter
+ {
+ private static readonly Guid UnassignedGuid = new Guid();
+
+ public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ if (storedValue == null || storedValue.Equals(UnassignedGuid))
+ {
+ storedValue = Guid.NewGuid();
+ property.SetPropertyValue(dictionaryAdapter, key, ref storedValue,
+ dictionaryAdapter.This.Descriptor);
+ }
+
+ return storedValue;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\OnDemandAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\OnDemandAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\OnDemandAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\OnDemandAttribute.cs Sun Feb 13 19:33:55 2011
@@ -0,0 +1,212 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Linq;
+ using System.Reflection;
+
+ ///
+ /// Support for on-demand value resolution.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = false)]
+ internal class OnDemandAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter
+ {
+ public OnDemandAttribute()
+ {
+ }
+
+ public OnDemandAttribute(Type type)
+ {
+ if (type.GetConstructor(Type.EmptyTypes) == null)
+ {
+ throw new ArgumentException("On-demand values must have a parameterless constructor");
+ }
+
+ Type = type;
+ }
+
+ public OnDemandAttribute(object value)
+ {
+ Value = value;
+ }
+
+ public Type Type { get; private set; }
+
+ public object Value { get; private set; }
+
+ public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key,
+ object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ if (storedValue == null && ifExists == false)
+ {
+ IValueInitializer initializer = null;
+
+ if (Value != null)
+ {
+ storedValue = Value;
+ }
+ else
+ {
+ var type = Type ?? GetInferredType(dictionaryAdapter, property, out initializer);
+
+ if (IsAcceptedType(type))
+ {
+ if (type.IsInterface)
+ {
+ if (property.IsDynamicProperty == false)
+ {
+ if (storedValue == null)
+ {
+ storedValue = dictionaryAdapter.Create(property.PropertyType);
+ }
+ }
+ }
+ else if (type.IsArray)
+ {
+ storedValue = Array.CreateInstance(type.GetElementType(), 0);
+ }
+ else
+ {
+ if (storedValue == null)
+ {
+ object[] args = null;
+ ConstructorInfo constructor = null;
+
+ if (property.IsDynamicProperty)
+ {
+ constructor =
+ (from ctor in type.GetConstructors()
+ let parms = ctor.GetParameters()
+ where parms.Length == 1 &&
+ parms[0].ParameterType.IsAssignableFrom(dictionaryAdapter.Meta.Type)
+ select ctor).FirstOrDefault();
+
+ if (constructor != null) args = new[] { dictionaryAdapter };
+ }
+
+ if (constructor == null)
+ {
+ constructor = type.GetConstructor(Type.EmptyTypes);
+ }
+
+ if (constructor != null)
+ {
+ storedValue = constructor.Invoke(args);
+ }
+ }
+ }
+ }
+ }
+
+ if (storedValue != null)
+ {
+ using (dictionaryAdapter.SuppressNotificationsBlock())
+ {
+#if !SL3
+ if (storedValue is ISupportInitialize)
+ {
+ ((ISupportInitialize)storedValue).BeginInit();
+ ((ISupportInitialize)storedValue).EndInit();
+ }
+#endif
+ if (initializer != null)
+ {
+ initializer.Initialize(dictionaryAdapter, storedValue);
+ }
+
+ property.SetPropertyValue(dictionaryAdapter, property.PropertyName,
+ ref storedValue, dictionaryAdapter.This.Descriptor);
+ }
+ }
+ }
+
+ return storedValue;
+ }
+
+ private bool IsAcceptedType(Type type)
+ {
+ return type != null && type != typeof(String) && !type.IsPrimitive && !type.IsEnum;
+ }
+
+ private Type GetInferredType(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property,
+ out IValueInitializer initializer)
+ {
+ Type type = null;
+ initializer = null;
+
+ type = property.PropertyType;
+ if (typeof(IEnumerable).IsAssignableFrom(type) == false)
+ {
+ return type;
+ }
+
+ Type collectionType = null;
+
+ if (type.IsGenericType)
+ {
+ var genericDef = type.GetGenericTypeDefinition();
+ var genericArg = type.GetGenericArguments()[0];
+ bool isBindingList =
+#if SILVERLIGHT
+ false;
+#else
+ genericDef == typeof(BindingList<>);
+#endif
+
+ if (isBindingList || genericDef == typeof(List<>))
+ {
+ if (dictionaryAdapter.CanEdit)
+ {
+#if SILVERLIGHT
+ collectionType = typeof(EditableList<>);
+#else
+ collectionType = isBindingList ? typeof(EditableBindingList<>) : typeof(EditableList<>);
+#endif
+ }
+
+#if SILVERLIGHT //never true
+#else
+ if (isBindingList && genericArg.IsInterface)
+ {
+ Func addNew = () => dictionaryAdapter.Create(genericArg);
+ initializer = (IValueInitializer)Activator.CreateInstance(
+ typeof(BindingListInitializer<>).MakeGenericType(genericArg),
+ null, addNew, null, null);
+ }
+#endif
+ }
+ else if (genericDef == typeof(IList<>) || genericDef == typeof(ICollection<>))
+ {
+ collectionType = dictionaryAdapter.CanEdit ? typeof(EditableList<>) : typeof(List<>);
+ }
+
+ if (collectionType != null)
+ {
+ return collectionType.MakeGenericType(genericArg);
+ }
+ }
+ else if (type == typeof(IList) || type == typeof(ICollection))
+ {
+ return dictionaryAdapter.CanEdit ? typeof(EditableList) : typeof(List);
+ }
+
+ return type;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\PropagateNotificationsAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\PropagateNotificationsAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\PropagateNotificationsAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\PropagateNotificationsAttribute.cs Sun Feb 13 19:34:00 2011
@@ -0,0 +1,37 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Suppress property change notifications.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = false)]
+ internal class PropagateNotificationsAttribute : DictionaryBehaviorAttribute, IDictionaryInitializer
+ {
+ public PropagateNotificationsAttribute(bool propagateNotifications)
+ {
+ PropagateNotifications = propagateNotifications;
+ }
+
+ public bool PropagateNotifications { get; private set; }
+
+ public void Initialize(IDictionaryAdapter dictionaryAdapter, object[] behaviors)
+ {
+ dictionaryAdapter.PropagateChildNotifications = PropagateNotifications;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringFormatAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringFormatAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringFormatAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringFormatAttribute.cs Sun Feb 13 19:34:04 2011
@@ -0,0 +1,77 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Provides simple string formatting from existing properties.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
+ internal class StringFormatAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter
+ {
+ private static readonly char[] PropertyDelimeters = new[] { ',', ' ' };
+
+ public StringFormatAttribute(string format, string properties)
+ {
+ if (format == null)
+ {
+ throw new ArgumentNullException("format");
+ }
+
+ Format = format;
+ Properties = properties;
+ }
+
+ ///
+ /// Gets the string format.
+ ///
+ public string Format { get; private set; }
+
+ ///
+ /// Gets the format properties.
+ ///
+ public string Properties { get; private set; }
+
+ #region IDictionaryPropertyGetter
+
+ object IDictionaryPropertyGetter.GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ return string.Format(Format, GetFormatArguments(dictionaryAdapter, property.Property.Name)).Trim();
+ }
+
+ #endregion
+
+ private object[] GetFormatArguments(IDictionaryAdapter dictionaryAdapter, string formattedPropertyName)
+ {
+ var properties = Properties.Split(PropertyDelimeters, StringSplitOptions.RemoveEmptyEntries);
+ var arguments = new object[properties.Length];
+ for (int i = 0; i < properties.Length; ++i)
+ {
+ var propertyName = properties[i];
+ if (propertyName != formattedPropertyName)
+ {
+ arguments[i] = dictionaryAdapter.GetProperty(propertyName, false);
+ }
+ else
+ {
+ arguments[i] = "(recursive)";
+ }
+ }
+ return arguments;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringListAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringListAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringListAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringListAttribute.cs Sun Feb 13 19:34:10 2011
@@ -0,0 +1,251 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Text;
+
+ ///
+ /// Identifies a property should be represented as a delimited string value.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ internal class StringListAttribute : DictionaryBehaviorAttribute,
+ IDictionaryPropertyGetter,
+ IDictionaryPropertySetter
+ {
+ private char separator = ',';
+
+ ///
+ /// Gets the separator.
+ ///
+ public char Separator
+ {
+ get { return separator; }
+ set { separator = value; }
+ }
+
+ #region IDictionaryPropertyGetter
+
+ object IDictionaryPropertyGetter.GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ var propertyType = property.PropertyType;
+
+ if (storedValue == null || !storedValue.GetType().IsInstanceOfType(propertyType))
+ {
+ if (propertyType.IsGenericType)
+ {
+ Type genericDef = propertyType.GetGenericTypeDefinition();
+
+ if (genericDef == typeof(IList<>) ||
+ genericDef == typeof(ICollection<>) ||
+ genericDef == typeof(List<>) ||
+ genericDef == typeof(IEnumerable<>))
+ {
+ var paramType = propertyType.GetGenericArguments()[0];
+ var converter = TypeDescriptor.GetConverter(paramType);
+
+ if (converter != null && converter.CanConvertFrom(typeof(string)))
+ {
+ var genericList = typeof(StringListWrapper<>).MakeGenericType(new[] {paramType});
+ return Activator.CreateInstance(genericList, key, storedValue, separator,
+ dictionaryAdapter.This.Dictionary);
+ }
+ }
+ }
+ }
+
+ return storedValue;
+ }
+
+ #endregion
+
+ #region IDictionaryPropertySetter Members
+
+ bool IDictionaryPropertySetter.SetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, ref object value, PropertyDescriptor property)
+ {
+ var enumerable = value as IEnumerable;
+ if (enumerable != null)
+ {
+ value = BuildString(enumerable, separator);
+ }
+ return true;
+ }
+
+ #endregion
+
+ internal static string BuildString(IEnumerable enumerable, char separator)
+ {
+ bool first = true;
+ var builder = new StringBuilder();
+
+ foreach(object item in enumerable)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ builder.Append(separator);
+ }
+
+ builder.Append(item.ToString());
+ }
+
+ return builder.ToString();
+ }
+ }
+
+ #region StringList
+
+ internal class StringListWrapper : IList
+ {
+ private readonly string key;
+ private readonly char separator;
+ private readonly IDictionary dictionary;
+ private readonly List inner;
+
+ public StringListWrapper(string key, string list,
+ char separator, IDictionary dictionary)
+ {
+ this.key = key;
+ this.separator = separator;
+ this.dictionary = dictionary;
+ inner = new List();
+
+ ParseList(list);
+ }
+
+ #region IList Members
+
+ public int IndexOf(T item)
+ {
+ return inner.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ inner.Insert(index, item);
+ SynchronizeDictionary();
+ }
+
+ public void RemoveAt(int index)
+ {
+ inner.RemoveAt(index);
+ SynchronizeDictionary();
+ }
+
+ public T this[int index]
+ {
+ get { return inner[index]; }
+ set
+ {
+ inner[index] = value;
+ SynchronizeDictionary();
+ }
+ }
+
+ #endregion
+
+ #region ICollection Members
+
+ public void Add(T item)
+ {
+ inner.Add(item);
+ SynchronizeDictionary();
+ }
+
+ public void Clear()
+ {
+ inner.Clear();
+ SynchronizeDictionary();
+ }
+
+ public bool Contains(T item)
+ {
+ return inner.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ inner.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return inner.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(T item)
+ {
+ if (inner.Remove(item))
+ {
+ SynchronizeDictionary();
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ public IEnumerator GetEnumerator()
+ {
+ return inner.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return inner.GetEnumerator();
+ }
+
+ #endregion
+
+ private void ParseList(string list)
+ {
+ if (list != null)
+ {
+ var converter = TypeDescriptor.GetConverter(typeof(T));
+
+ foreach(var item in list.Split(separator))
+ {
+ inner.Add((T) converter.ConvertFrom(item));
+ }
+ }
+ }
+
+ private void SynchronizeDictionary()
+ {
+ dictionary[key] = StringListAttribute.BuildString(inner, separator);
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringStorageAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringStorageAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringStorageAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringStorageAttribute.cs Sun Feb 13 19:34:16 2011
@@ -0,0 +1,26 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License";
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ internal class StringStorageAttribute : DictionaryBehaviorAttribute, IDictionaryPropertySetter
+ {
+ public bool SetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key,
+ ref object value, PropertyDescriptor property)
+ {
+ value = (value != null) ? value.ToString() : null;
+ return true;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringValuesAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringValuesAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringValuesAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\StringValuesAttribute.cs Sun Feb 13 19:34:21 2011
@@ -0,0 +1,70 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Converts all properties to strings.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property,
+ AllowMultiple = false, Inherited = true)]
+ internal class StringValuesAttribute : DictionaryBehaviorAttribute, IDictionaryPropertySetter
+ {
+ private string format;
+
+ ///
+ /// Gets or sets the format.
+ ///
+ /// The format.
+ public string Format
+ {
+ get { return format; }
+ set { format = value; }
+ }
+
+ #region IDictionaryPropertySetter Members
+
+ bool IDictionaryPropertySetter.SetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, ref object value, PropertyDescriptor property)
+ {
+ if (value != null)
+ {
+ value = GetPropertyAsString(property, value);
+ }
+ return true;
+ }
+
+ #endregion
+
+ private string GetPropertyAsString(PropertyDescriptor property, object value)
+ {
+ if (!string.IsNullOrEmpty(format))
+ {
+ return String.Format(format, value);
+ }
+
+ var converter = property.TypeConverter;
+
+ if (converter != null && converter.CanConvertTo(typeof(string)))
+ {
+ return (string) converter.ConvertTo(value, typeof(string));
+ }
+
+ return value.ToString();
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\SuppressNotificationsAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\SuppressNotificationsAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\SuppressNotificationsAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\SuppressNotificationsAttribute.cs Sun Feb 13 19:34:25 2011
@@ -0,0 +1,30 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Suppress property change notifications.
+ ///
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
+ internal class SuppressNotificationsAttribute : DictionaryBehaviorAttribute, IPropertyDescriptorInitializer
+ {
+ public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
+ {
+ propertyDescriptor.SuppressNotifications = true;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\TypeKeyPrefixAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\TypeKeyPrefixAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\TypeKeyPrefixAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\TypeKeyPrefixAttribute.cs Sun Feb 13 19:34:31 2011
@@ -0,0 +1,32 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Assigns a prefix to the keyed properties using the interface name.
+ ///
+ [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
+ internal class TypeKeyPrefixAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
+ {
+ String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter,
+ String key, PropertyDescriptor property)
+ {
+ return property.Property.DeclaringType.FullName + "#" + key;
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XmlNamespaceAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XmlNamespaceAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XmlNamespaceAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XmlNamespaceAttribute.cs Sun Feb 13 19:34:35 2011
@@ -0,0 +1,34 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true)]
+ internal class XmlNamespaceAttribute : Attribute
+ {
+ public XmlNamespaceAttribute(string namespaceUri, string prefix)
+ {
+ NamespaceUri = namespaceUri;
+ Prefix = prefix;
+ }
+
+ public bool Default { get; set; }
+
+ public string NamespaceUri { get; private set; }
+
+ public string Prefix { get; private set; }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathAttribute.cs Sun Feb 13 19:34:40 2011
@@ -0,0 +1,44 @@
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.Xml.XPath;
+
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true)]
+ internal class XPathAttribute : Attribute
+ {
+ private string expression;
+
+ public XPathAttribute(string expression)
+ {
+ Expression = expression;
+ }
+
+ public string Expression
+ {
+ get { return expression; }
+ private set
+ {
+ expression = value;
+ CompiledExpression = XPathExpression.Compile(expression);
+ }
+ }
+
+ public XPathExpression CompiledExpression { get; private set; }
+ }
+#endif
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathFunctionAttribute.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathFunctionAttribute.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathFunctionAttribute.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Attributes\XPathFunctionAttribute.cs Sun Feb 13 19:34:45 2011
@@ -0,0 +1,55 @@
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.Xml.Xsl;
+
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true)]
+ internal class XPathFunctionAttribute : Attribute
+ {
+ protected XPathFunctionAttribute(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ {
+ throw new ArgumentException("Name cannot be empty", "name");
+ }
+ Name = name;
+ }
+
+ public XPathFunctionAttribute(string name, Type functionType) : this(name)
+ {
+ if (typeof(IXsltContextFunction).IsAssignableFrom(functionType) == false)
+ {
+ throw new ArgumentException("The functionType does not implement IXsltContextFunction");
+ }
+
+ var defaultCtor = functionType.GetConstructor(Type.EmptyTypes);
+ if (defaultCtor == null)
+ {
+ throw new ArgumentException("The functionType does not have a parameterless constructor");
+ }
+ Function = (IXsltContextFunction)Activator.CreateInstance(functionType);
+ }
+
+ public string Name { get; private set; }
+
+ public IXsltContextFunction Function { get; protected set; }
+
+ public string Prefix { get; set; }
+ }
+#endif
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\CascadingDictionaryAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\CascadingDictionaryAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\CascadingDictionaryAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\CascadingDictionaryAdapter.cs Sun Feb 13 19:16:40 2011
@@ -0,0 +1,56 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections;
+
+ internal class CascadingDictionaryAdapter : AbstractDictionaryAdapter
+ {
+ private readonly IDictionary primary;
+ private readonly IDictionary secondary;
+
+ public CascadingDictionaryAdapter(IDictionary primary, IDictionary secondary)
+ {
+ this.primary = primary;
+ this.secondary = secondary;
+ }
+
+ public IDictionary Primary
+ {
+ get { return primary; }
+ }
+
+ public IDictionary Secondary
+ {
+ get { return secondary; }
+ }
+
+ public override bool IsReadOnly
+ {
+ get { return primary.IsReadOnly; }
+ }
+
+ public override bool Contains(object key)
+ {
+ return primary.Contains(key) || secondary.Contains(key);
+ }
+
+ public override object this[object key]
+ {
+ get { return primary[key] ?? secondary[key]; }
+ set { primary[key] = value; }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultPropertyGetter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultPropertyGetter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultPropertyGetter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultPropertyGetter.cs Sun Feb 13 19:16:45 2011
@@ -0,0 +1,68 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.ComponentModel;
+
+ ///
+ /// Manages conversion between property values.
+ ///
+ internal class DefaultPropertyGetter : IDictionaryPropertyGetter
+ {
+ private readonly TypeConverter converter;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The converter.
+ public DefaultPropertyGetter(TypeConverter converter)
+ {
+ this.converter = converter;
+ }
+
+ ///
+ ///
+ ///
+ public int ExecutionOrder
+ {
+ get { return DictionaryBehaviorAttribute.LastExecutionOrder; }
+ }
+
+ ///
+ /// Gets the effective dictionary value.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The stored value.
+ /// The property.
+ /// true if return only existing.
+ /// The effective property value.
+ public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ var propertyType = property.PropertyType;
+
+ if (storedValue != null && propertyType.IsInstanceOfType(storedValue) == false)
+ {
+ if (converter != null && converter.CanConvertFrom(storedValue.GetType()))
+ {
+ return converter.ConvertFrom(storedValue);
+ }
+ }
+
+ return storedValue;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultXmlSerializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultXmlSerializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultXmlSerializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DefaultXmlSerializer.cs Sun Feb 13 19:16:50 2011
@@ -0,0 +1,90 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if !SILVERLIGHT
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Text;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using System.Xml.XPath;
+
+ internal class DefaultXmlSerializer : IXPathSerializer
+ {
+ public static readonly DefaultXmlSerializer Instance = new DefaultXmlSerializer();
+
+ private DefaultXmlSerializer()
+ {
+ }
+
+ public bool WriteObject(XPathResult result, XPathNavigator node, object value)
+ {
+ var rootOverride = new XmlRootAttribute(node.LocalName)
+ {
+ Namespace = node.NamespaceURI
+ };
+
+ var xml = new StringBuilder();
+ var settings = new XmlWriterSettings
+ {
+ OmitXmlDeclaration = true,
+ Indent = false
+ };
+ var namespaces = new XmlSerializerNamespaces();
+ namespaces.Add(string.Empty, string.Empty);
+ if (string.IsNullOrEmpty(node.NamespaceURI) == false)
+ {
+ var prefix = result.Context.AddNamespace(node.NamespaceURI);
+ namespaces.Add(prefix, node.NamespaceURI);
+ }
+
+ var serializer = new XmlSerializer(result.Type, rootOverride);
+
+ using (var writer = XmlWriter.Create(xml, settings))
+ {
+ serializer.Serialize(writer, value, namespaces);
+ writer.Flush();
+ }
+
+ node.ReplaceSelf(xml.ToString());
+
+ return true;
+ }
+
+ public bool ReadObject(XPathResult result, XPathNavigator node, out object value)
+ {
+ var rootOverride = new XmlRootAttribute(node.LocalName)
+ {
+ Namespace = node.NamespaceURI
+ };
+
+ var serializer = new XmlSerializer(result.Type, rootOverride);
+
+ using (var reader = node.ReadSubtree())
+ {
+ reader.MoveToContent();
+ if (serializer.CanDeserialize(reader))
+ {
+ value = serializer.Deserialize(reader);
+ return true;
+ }
+ }
+
+ value = null;
+ return false;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Create.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Create.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Create.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Create.cs Sun Feb 13 19:28:11 2011
@@ -0,0 +1,66 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+#if !SILVERLIGHT
+ using System.Collections.Specialized;
+#else
+ using HybridDictionary = System.Collections.Generic.Dictionary;
+#endif
+ internal abstract partial class DictionaryAdapterBase : IDictionaryCreate
+ {
+ public T Create()
+ {
+ return Create(new HybridDictionary());
+ }
+
+ public object Create(Type type)
+ {
+ return Create(type, new HybridDictionary());
+ }
+
+ public T Create(IDictionary dictionary)
+ {
+ return (T)Create(typeof(T), dictionary ?? new HybridDictionary());
+ }
+
+ public object Create(Type type, IDictionary dictionary)
+ {
+ if (This.CreateStrategy != null)
+ {
+ return This.CreateStrategy.Create(this, type, dictionary);
+ }
+ else
+ {
+ dictionary = dictionary ?? new HybridDictionary();
+ return This.Factory.GetAdapter(type, dictionary, This.Descriptor);
+ }
+ }
+
+ public T Create(Action init)
+ {
+ return Create(new HybridDictionary(), init);
+ }
+
+ public T Create(IDictionary dictionary, Action init)
+ {
+ var adapter = Create(dictionary ?? new HybridDictionary());
+ if (init != null) init(adapter);
+ return adapter;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.cs Sun Feb 13 19:28:16 2011
@@ -0,0 +1,235 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Linq;
+
+ internal abstract partial class DictionaryAdapterBase : IDictionaryAdapter
+ {
+ public DictionaryAdapterBase(DictionaryAdapterInstance instance)
+ {
+ This = instance;
+
+ CanEdit = typeof(IEditableObject).IsAssignableFrom(Meta.Type);
+ CanNotify = typeof(INotifyPropertyChanged).IsAssignableFrom(Meta.Type);
+ CanValidate = typeof(IDataErrorInfo).IsAssignableFrom(Meta.Type);
+
+ Initialize();
+ }
+
+ public abstract DictionaryAdapterMeta Meta { get; }
+
+ public DictionaryAdapterInstance This { get; private set; }
+
+ public string GetKey(string propertyName)
+ {
+ PropertyDescriptor descriptor;
+ if (This.Properties.TryGetValue(propertyName, out descriptor))
+ {
+ return descriptor.GetKey(this, propertyName, This.Descriptor);
+ }
+ return null;
+ }
+
+ public virtual object GetProperty(string propertyName, bool ifExists)
+ {
+ PropertyDescriptor descriptor;
+ if (This.Properties.TryGetValue(propertyName, out descriptor))
+ {
+ var propertyValue = descriptor.GetPropertyValue(this, propertyName, null, This.Descriptor, ifExists);
+ if (propertyValue is IEditableObject)
+ {
+ AddEditDependency((IEditableObject)propertyValue);
+ }
+ ComposeChildNotifications(descriptor, null, propertyValue);
+ return propertyValue;
+ }
+ return null;
+ }
+
+ public T GetPropertyOfType(string propertyName)
+ {
+ var propertyValue = GetProperty(propertyName, false);
+ return propertyValue != null ? (T)propertyValue : default(T);
+ }
+
+ public object ReadProperty(string key)
+ {
+ object propertyValue = null;
+ if (GetEditedProperty(key, out propertyValue) == false)
+ {
+ var dictionary = GetDictionary(This.Dictionary, ref key);
+ if (dictionary != null) propertyValue = dictionary[key];
+ }
+ return propertyValue;
+ }
+
+ public virtual bool SetProperty(string propertyName, ref object value)
+ {
+ bool stored = false;
+
+ PropertyDescriptor descriptor;
+ if (This.Properties.TryGetValue(propertyName, out descriptor))
+ {
+ if (ShouldNotify == false)
+ {
+ stored = descriptor.SetPropertyValue(this, propertyName, ref value, This.Descriptor);
+ Invalidate();
+ return stored;
+ }
+
+ var existingValue = GetProperty(propertyName, true);
+ if (NotifyPropertyChanging(descriptor, existingValue, value) == false)
+ {
+ return false;
+ }
+
+ var trackPropertyChange = TrackPropertyChange(descriptor, existingValue, value);
+
+ stored = descriptor.SetPropertyValue(this, propertyName, ref value, This.Descriptor);
+
+ if (stored && trackPropertyChange != null)
+ {
+ trackPropertyChange.Notify();
+ }
+ }
+
+ return stored;
+ }
+
+ public void StoreProperty(PropertyDescriptor property, string key, object value)
+ {
+ if (property == null || EditProperty(property, key, value) == false)
+ {
+ var dictionary = GetDictionary(This.Dictionary, ref key);
+ if (dictionary != null) dictionary[key] = value;
+ }
+ }
+
+ public void ClearProperty(PropertyDescriptor property, string key)
+ {
+ if (property == null || ClearEditProperty(property, key) == false)
+ {
+ var dictionary = GetDictionary(This.Dictionary, ref key);
+ if (dictionary != null) dictionary.Remove(key);
+ }
+ }
+
+ public void CopyTo(IDictionaryAdapter other)
+ {
+ CopyTo(other, null);
+ }
+
+ public void CopyTo(IDictionaryAdapter other, Predicate selector)
+ {
+ if (Meta.Type.IsAssignableFrom(other.Meta.Type) == false)
+ {
+ throw new ArgumentException(string.Format(
+ "Unable to copy to {0}. Type must be assignable from {1}.",
+ other.Meta.Type.FullName, Meta.Type.FullName));
+ }
+
+ selector = selector ?? (p => true);
+
+ foreach (var property in This.Properties.Values.Where(p => selector(p)))
+ {
+ var propertyValue = GetProperty(property.PropertyName, true);
+ if (propertyValue != null)
+ other.SetProperty(property.PropertyName, ref propertyValue);
+ }
+ }
+
+ public T Coerce() where T : class
+ {
+ return (T)This.Factory.GetAdapter(typeof(T), This.Dictionary, This.Descriptor);
+ }
+
+ public override bool Equals(object obj)
+ {
+ var other = obj as IDictionaryAdapter;
+
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (Meta.Type != other.Meta.Type)
+ {
+ return false;
+ }
+
+ if (This.EqualityHashCodeStrategy != null)
+ {
+ return This.EqualityHashCodeStrategy.Equals(this, other);
+ }
+
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ if (This.OldHashCode.HasValue)
+ {
+ return This.OldHashCode.Value;
+ }
+
+ int hashCode;
+ if (This.EqualityHashCodeStrategy == null ||
+ This.EqualityHashCodeStrategy.GetHashCode(this, out hashCode) == false)
+ {
+ hashCode = base.GetHashCode();
+ }
+
+ This.OldHashCode = hashCode;
+ return hashCode;
+ }
+
+ protected void Initialize()
+ {
+ foreach (var initializer in This.Initializers)
+ {
+ initializer.Initialize(this, Meta.Behaviors);
+ }
+
+ foreach (var property in This.Properties.Values.Where(p => p.Fetch))
+ {
+ GetProperty(property.PropertyName, false);
+ }
+ }
+
+ private static IDictionary GetDictionary(IDictionary dictionary, ref string key)
+ {
+ if (key.StartsWith("!") == false)
+ {
+ var parts = key.Split(',');
+ for (var i = 0; i < parts.Length - 1; ++i)
+ {
+ dictionary = dictionary[parts[i]] as IDictionary;
+ if (dictionary == null) return null;
+ }
+ key = parts[parts.Length - 1];
+ }
+ return dictionary;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Edit.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Edit.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Edit.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Edit.cs Sun Feb 13 19:28:21 2011
@@ -0,0 +1,265 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Linq;
+
+ internal abstract partial class DictionaryAdapterBase
+ {
+ private int suppressEditingCount = 0;
+ private Stack> updates;
+#if SL3
+ private List editDependencies;
+#else
+ private HashSet editDependencies;
+#endif
+ struct Edit
+ {
+ public Edit(PropertyDescriptor property, object propertyValue)
+ {
+ Property = property;
+ PropertyValue = propertyValue;
+ }
+ public readonly PropertyDescriptor Property;
+ public object PropertyValue;
+ }
+
+ public bool CanEdit
+ {
+ get { return suppressEditingCount == 0 && updates != null; }
+ set { updates = value ? new Stack>() : null; }
+ }
+
+ public bool IsEditing
+ {
+ get { return CanEdit && updates != null && updates.Count > 0; }
+ }
+
+ public bool SupportsMultiLevelEdit { get; set; }
+
+ public bool IsChanged
+ {
+ get
+ {
+ if (IsEditing && updates.Any(level => level.Count > 0))
+ return true;
+
+ return This.Properties.Values
+ .Where(prop => typeof(IChangeTracking).IsAssignableFrom(prop.PropertyType))
+ .Select(prop => GetProperty(prop.PropertyName, true))
+ .Cast().Any(track => track != null && track.IsChanged);
+ }
+ }
+
+ public void BeginEdit()
+ {
+ if (CanEdit && (IsEditing == false || SupportsMultiLevelEdit))
+ {
+ updates.Push(new Dictionary());
+ }
+ }
+
+ public void CancelEdit()
+ {
+ if (IsEditing)
+ {
+ if (editDependencies != null)
+ {
+ foreach (var editDependency in editDependencies.ToArray())
+ {
+ editDependency.CancelEdit();
+ }
+ editDependencies.Clear();
+ }
+
+ using (SuppressEditingBlock())
+ {
+ using (TrackReadonlyPropertyChanges())
+ {
+ var top = updates.Peek();
+
+ if (top.Count > 0)
+ {
+ foreach (var update in top.Values)
+ {
+ var existing = update;
+ existing.PropertyValue = GetProperty(existing.Property.PropertyName, true);
+ }
+
+ updates.Pop();
+
+ foreach (var update in top.Values.ToArray())
+ {
+ var oldValue = update.PropertyValue;
+ var newValue = GetProperty(update.Property.PropertyName, true);
+
+ if (!Object.Equals(oldValue, newValue))
+ {
+
+ NotifyPropertyChanging(update.Property, oldValue, newValue);
+ NotifyPropertyChanged(update.Property, oldValue, newValue);
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void EndEdit()
+ {
+ if (IsEditing)
+ {
+ using (SuppressEditingBlock())
+ {
+ var top = updates.Pop();
+
+ if (top.Count > 0) foreach (var update in top.ToArray())
+ {
+ StoreProperty(null, update.Key, update.Value.PropertyValue);
+ }
+ }
+
+ if (editDependencies != null)
+ {
+ foreach (var editDependency in editDependencies.ToArray())
+ {
+ editDependency.EndEdit();
+ }
+ editDependencies.Clear();
+ }
+ }
+ }
+
+ public void RejectChanges()
+ {
+ CancelEdit();
+ }
+
+ public void AcceptChanges()
+ {
+ EndEdit();
+ }
+
+ public IDisposable SuppressEditingBlock()
+ {
+ return new SuppressEditingScope(this);
+ }
+
+ public void SuppressEditing()
+ {
+ ++suppressEditingCount;
+ }
+
+ public void ResumeEditing()
+ {
+ --suppressEditingCount;
+ }
+
+ protected bool GetEditedProperty(string propertyName, out object propertyValue)
+ {
+ if (updates != null) foreach (var level in updates.ToArray())
+ {
+ Edit edit;
+ if (level.TryGetValue(propertyName, out edit))
+ {
+ propertyValue = edit.PropertyValue;
+ return true;
+ }
+ }
+ propertyValue = null;
+ return false;
+ }
+
+ protected bool EditProperty(PropertyDescriptor property, string key, object propertyValue)
+ {
+ if (IsEditing)
+ {
+ updates.Peek()[key] = new Edit(property, propertyValue);
+ return true;
+ }
+ return false;
+ }
+
+ protected bool ClearEditProperty(PropertyDescriptor property, string key)
+ {
+ if (IsEditing)
+ {
+ updates.Peek().Remove(key);
+ return true;
+ }
+ return false;
+ }
+
+ protected void AddEditDependency(IEditableObject editDependency)
+ {
+ if (IsEditing)
+ {
+ if (editDependencies == null)
+ {
+#if SL3
+ editDependencies = new List();
+#else
+ editDependencies = new HashSet();
+#endif
+ }
+
+#if SL3
+ if(AddDependency(editDependency))
+#else
+ if (editDependencies.Add(editDependency))
+#endif
+ {
+ editDependency.BeginEdit();
+ }
+ }
+ }
+#if SL3
+ private bool AddDependency(IEditableObject editDependency)
+ {
+ if (editDependencies.Contains(editDependency))
+ {
+ return false;
+ }
+ editDependencies.Add(editDependency);
+ return true;
+ }
+#endif
+
+ #region Nested Class: SuppressEditingScope
+
+ class SuppressEditingScope : IDisposable
+ {
+ private readonly DictionaryAdapterBase adapter;
+
+ public SuppressEditingScope(DictionaryAdapterBase adapter)
+ {
+ this.adapter = adapter;
+ this.adapter.SuppressEditing();
+ }
+
+ public void Dispose()
+ {
+ adapter.ResumeEditing();
+ }
+ }
+
+ #endregion
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Notify.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Notify.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Notify.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Notify.cs Sun Feb 13 19:28:26 2011
@@ -0,0 +1,329 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Linq;
+
+ internal abstract partial class DictionaryAdapterBase
+ {
+ private int suppressNotificationCount = 0;
+ private bool propagateChildNotifications = true;
+ private Dictionary composedChildNotifications;
+
+ [ThreadStatic]
+ private static TrackPropertyChangeScope readonlyTrackingScope;
+
+ public event PropertyChangingEventHandler PropertyChanging;
+ public event PropertyChangedEventHandler PropertyChanged;
+
+
+ public bool CanNotify { get; set; }
+
+ public bool ShouldNotify
+ {
+ get { return CanNotify && suppressNotificationCount == 0; }
+ }
+
+ public bool PropagateChildNotifications
+ {
+ get { return propagateChildNotifications; }
+ set { propagateChildNotifications = value; }
+ }
+
+ public IDisposable SuppressNotificationsBlock()
+ {
+ return new SuppressNotificationsScope(this);
+ }
+
+ public void SuppressNotifications()
+ {
+ ++suppressNotificationCount;
+ }
+
+ public void ResumeNotifications()
+ {
+ --suppressNotificationCount;
+ }
+ protected bool NotifyPropertyChanging(PropertyDescriptor property, object oldValue, object newValue)
+ {
+ if (!property.SuppressNotifications)
+ {
+ var propertyChanging = PropertyChanging;
+
+ if (propertyChanging != null)
+ {
+ var eventArgs = new PropertyModifyingEventArgs(property.PropertyName, oldValue, newValue);
+ propertyChanging(this, eventArgs);
+ return !eventArgs.Cancel;
+ }
+ }
+ return true;
+ }
+
+ protected void NotifyPropertyChanged(PropertyDescriptor property, object oldValue, object newValue)
+ {
+ if (!property.SuppressNotifications)
+ {
+ var propertyChanged = PropertyChanged;
+
+ ComposeChildNotifications(property, oldValue, newValue);
+
+ if (propertyChanged != null)
+ {
+ propertyChanged(this, new PropertyModifiedEventArgs(property.PropertyName, oldValue, newValue));
+ }
+ }
+ }
+
+ protected void NotifyPropertyChanged(string propertyName)
+ {
+ if (ShouldNotify)
+ {
+ var propertyChanged = PropertyChanged;
+
+ if (propertyChanged != null)
+ {
+ propertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+
+ protected TrackPropertyChangeScope TrackPropertyChange(PropertyDescriptor property,
+ object oldValue, object newValue)
+ {
+ if (ShouldNotify && !property.SuppressNotifications)
+ {
+ return new TrackPropertyChangeScope(this, property, oldValue);
+ }
+ return null;
+ }
+
+ protected TrackPropertyChangeScope TrackReadonlyPropertyChanges()
+ {
+ if (ShouldNotify && readonlyTrackingScope == null)
+ {
+ var scope = new TrackPropertyChangeScope(this);
+ readonlyTrackingScope = scope;
+ return scope;
+ }
+ return null;
+ }
+
+ private void ComposeChildNotifications(PropertyDescriptor property, object oldValue, object newValue)
+ {
+ if (composedChildNotifications == null)
+ composedChildNotifications = new Dictionary();
+
+ if (oldValue != null)
+ {
+ object handler;
+ if (composedChildNotifications.TryGetValue(oldValue, out handler))
+ {
+ composedChildNotifications.Remove(oldValue);
+
+ if (oldValue is INotifyPropertyChanged)
+ {
+ ((INotifyPropertyChanged)oldValue).PropertyChanged -= Child_PropertyChanged;
+#if !SILVERLIGHT
+ if (oldValue is INotifyPropertyChanging)
+ {
+ ((INotifyPropertyChanging)oldValue).PropertyChanging -= Child_PropertyChanging;
+ }
+ }
+ else if (oldValue is IBindingList)
+ {
+ ((IBindingList)oldValue).ListChanged -= (ListChangedEventHandler)handler;
+#endif
+ }
+ }
+ }
+
+ if (newValue != null && !composedChildNotifications.ContainsKey(newValue))
+ {
+ if (newValue is INotifyPropertyChanged)
+ {
+ ((INotifyPropertyChanged)newValue).PropertyChanged += Child_PropertyChanged;
+
+#if !SILVERLIGHT
+ if (newValue is INotifyPropertyChanging)
+ {
+ ((INotifyPropertyChanging)newValue).PropertyChanging += Child_PropertyChanging;
+ }
+
+ composedChildNotifications.Add(newValue, null);
+ }
+ else if (newValue is IBindingList)
+ {
+ ListChangedEventHandler handler = (sender, args) =>
+ {
+ if (propagateChildNotifications)
+ {
+ var propertyChanged = PropertyChanged;
+
+ if (propertyChanged != null)
+ {
+ if (args.PropertyDescriptor != null)
+ {
+ var propertyName = args.PropertyDescriptor.Name;
+ propertyChanged(sender, new PropertyChangedEventArgs(propertyName));
+ }
+ propertyChanged(this, new PropertyChangedEventArgs(property.PropertyName));
+ }
+ }
+ };
+ ((IBindingList)newValue).ListChanged += handler;
+
+ composedChildNotifications.Add(newValue, handler);
+#endif
+ }
+ }
+ }
+
+ private void Child_PropertyChanging(object sender, PropertyChangingEventArgs e)
+ {
+ if (propagateChildNotifications)
+ {
+ var propertyChanging = PropertyChanging;
+
+ if (propertyChanging != null)
+ {
+ propertyChanging(sender, e);
+ }
+ }
+ }
+
+ private void Child_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (propagateChildNotifications)
+ {
+ var propertyChanged = PropertyChanged;
+
+ if (propertyChanged != null)
+ {
+ propertyChanged(sender, e);
+ }
+ }
+ }
+
+ #region Nested Class: SuppressNotificationsScope
+
+ class SuppressNotificationsScope : IDisposable
+ {
+ private readonly DictionaryAdapterBase adapter;
+
+ public SuppressNotificationsScope(DictionaryAdapterBase adapter)
+ {
+ this.adapter = adapter;
+ this.adapter.SuppressNotifications();
+ }
+
+ public void Dispose()
+ {
+ this.adapter.ResumeNotifications();
+ }
+ }
+
+ #endregion
+
+ #region Nested Class: TrackPropertyChangeScope
+
+ public class TrackPropertyChangeScope : IDisposable
+ {
+ private readonly DictionaryAdapterBase adapter;
+ private readonly PropertyDescriptor property;
+ private readonly object existingValue;
+ private IDictionary readonlyProperties;
+
+ public TrackPropertyChangeScope(DictionaryAdapterBase adapter)
+ {
+ this.adapter = adapter;
+ readonlyProperties = adapter.This.Properties.Values.Where(
+ pd => !pd.Property.CanWrite || pd.IsDynamicProperty)
+ .ToDictionary(pd => pd, pd => GetEffectivePropertyValue(pd));
+ }
+
+ public TrackPropertyChangeScope(DictionaryAdapterBase adapter, PropertyDescriptor property,
+ object existingValue)
+ : this(adapter)
+ {
+ this.property = property;
+ this.existingValue = existingValue;
+ existingValue = adapter.GetProperty(property.PropertyName, true);
+ }
+
+ public bool Notify()
+ {
+ if (readonlyTrackingScope == this)
+ {
+ readonlyTrackingScope = null;
+ return NotifyReadonly();
+ }
+
+ var newValue = GetEffectivePropertyValue(property);
+ if (NotifyIfChanged(property, existingValue, newValue))
+ {
+ if (readonlyTrackingScope == null)
+ NotifyReadonly();
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool NotifyReadonly()
+ {
+ bool changed = false;
+ foreach (var readonlyProperty in readonlyProperties)
+ {
+ var descriptor = readonlyProperty.Key;
+ var currentValue = GetEffectivePropertyValue(descriptor);
+ changed |= NotifyIfChanged(descriptor, readonlyProperty.Value, currentValue);
+ }
+ adapter.Invalidate();
+ return changed;
+ }
+
+ private bool NotifyIfChanged(PropertyDescriptor descriptor, object oldValue, object newValue)
+ {
+ if (!Object.Equals(oldValue, newValue))
+ {
+ adapter.NotifyPropertyChanged(descriptor, oldValue, newValue);
+ return true;
+ }
+ return false;
+ }
+
+ private object GetEffectivePropertyValue(PropertyDescriptor property)
+ {
+ var value = adapter.GetProperty(property.PropertyName, true);
+ if (value != null & property.IsDynamicProperty)
+ {
+ value = ((IDynamicValue)value).GetValue();
+ }
+ return value;
+ }
+
+ public void Dispose()
+ {
+ Notify();
+ }
+ }
+
+ #endregion
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Validate.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Validate.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Validate.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterBase.Validate.cs Sun Feb 13 19:28:31 2011
@@ -0,0 +1,114 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ internal partial class DictionaryAdapterBase : IDictionaryValidate
+ {
+ private ICollection validators;
+
+ public bool CanValidate { get; set; }
+
+ public bool IsValid
+ {
+ get
+ {
+ if (CanValidate && validators != null)
+ {
+ return !validators.Any(v => !v.IsValid(this));
+ }
+ return !CanValidate;
+ }
+ }
+
+ public string Error
+ {
+ get
+ {
+ if (CanValidate && validators != null)
+ {
+ return string.Join(Environment.NewLine, validators.Select(
+ v => v.Validate(this)).Where(e => !string.IsNullOrEmpty(e)).ToArray());
+ }
+ return String.Empty;
+ }
+ }
+
+ public string this[String columnName]
+ {
+ get
+ {
+ if (CanValidate && validators != null)
+ {
+ PropertyDescriptor property;
+ if (This.Properties.TryGetValue(columnName, out property))
+ {
+ return string.Join(Environment.NewLine, validators.Select(
+ v => v.Validate(this, property)).Where(e => !string.IsNullOrEmpty(e))
+ .ToArray());
+ }
+ }
+ return String.Empty;
+ }
+ }
+
+ public DictionaryValidateGroup ValidateGroups(params object[] groups)
+ {
+ return new DictionaryValidateGroup(groups, this);
+ }
+
+ public IEnumerable Validators
+ {
+ get
+ {
+ return validators ?? Enumerable.Empty();
+ }
+ }
+
+ public void AddValidator(IDictionaryValidator validator)
+ {
+ if (validators == null)
+ {
+ validators =
+#if SL3 //Silverlight 3 does not have HashSet
+ new List();
+#else
+ new HashSet();
+#endif
+ }
+#if SL3 //Silverlight 3 does not have HashSet
+ if(validators.Contains(validator)) return;
+#else
+ validators.Add(validator);
+#endif
+ }
+
+ protected internal void Invalidate()
+ {
+ if (CanValidate)
+ {
+ if (validators != null) foreach (var validator in validators)
+ {
+ validator.Invalidate(this);
+ }
+
+ NotifyPropertyChanged("IsValid");
+ }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterFactory.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterFactory.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterFactory.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterFactory.cs Sun Feb 13 19:28:37 2011
@@ -0,0 +1,627 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+#if !SILVERLIGHT
+ using System.Collections.Specialized;
+#endif
+ using System.ComponentModel;
+ using System.Linq;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Text;
+ using System.Threading;
+#if !SILVERLIGHT
+ using System.Xml.XPath;
+#endif
+ using System.Diagnostics;
+
+ using Castle.Core.Internal;
+
+ ///
+ /// Uses Reflection.Emit to expose the properties of a dictionary
+ /// through a dynamic implementation of a typed interface.
+ ///
+ internal class DictionaryAdapterFactory : IDictionaryAdapterFactory
+ {
+ private readonly Dictionary interfaceToAdapter = new Dictionary();
+ private readonly object typesDictionaryLocker = new object();
+
+ #region IDictionaryAdapterFactory
+
+ ///
+ public T GetAdapter(IDictionary dictionary)
+ {
+ return (T) GetAdapter(typeof(T), dictionary);
+ }
+
+ ///
+ public object GetAdapter(Type type, IDictionary dictionary)
+ {
+ return InternalGetAdapter(type, dictionary, null);
+ }
+
+ ///
+ public object GetAdapter(Type type, IDictionary dictionary, PropertyDescriptor descriptor)
+ {
+ return InternalGetAdapter(type, dictionary, descriptor);
+ }
+
+ ///
+ public T GetAdapter(IDictionary dictionary)
+ {
+ return (T) GetAdapter(typeof(T), dictionary);
+ }
+
+ ///
+ public object GetAdapter(Type type, IDictionary dictionary)
+ {
+ var adapter = new GenericDictionaryAdapter(dictionary);
+ return InternalGetAdapter(type, adapter, null);
+ }
+
+#if! SILVERLIGHT
+ ///
+ public T GetAdapter(NameValueCollection nameValues)
+ {
+ return GetAdapter(new NameValueCollectionAdapter(nameValues));
+ }
+
+ ///
+ public object GetAdapter(Type type, NameValueCollection nameValues)
+ {
+ return GetAdapter(type, new NameValueCollectionAdapter(nameValues));
+ }
+
+ ///
+ public T GetAdapter(IXPathNavigable xpathNavigable)
+ {
+ return (T)GetAdapter(typeof(T), xpathNavigable);
+ }
+
+ ///
+ public object GetAdapter(Type type, IXPathNavigable xpathNavigable)
+ {
+ var xpath = new XPathAdapter(xpathNavigable);
+ return GetAdapter(type, new Hashtable(), new DictionaryDescriptor()
+ .AddBehavior(XPathBehavior.Instance).AddBehavior(xpath));
+ }
+#endif
+
+ ///
+ public DictionaryAdapterMeta GetAdapterMeta(Type type)
+ {
+ return GetAdapterMeta(type, null);
+ }
+
+ ///
+ public DictionaryAdapterMeta GetAdapterMeta(Type type, PropertyDescriptor descriptor)
+ {
+ if (type.IsInterface == false)
+ {
+ throw new ArgumentException("Only interfaces can be adapted and have metadata");
+ }
+
+ var adapterType = InternalGetAdapterType(type, descriptor);
+ var metaBindings = BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField;
+ return (DictionaryAdapterMeta)adapterType.InvokeMember("__meta", metaBindings, null, null, null);
+ }
+
+ #endregion
+
+ private Type InternalGetAdapterType(Type type, PropertyDescriptor descriptor)
+ {
+ if (type.IsInterface == false)
+ {
+ throw new ArgumentException("Only interfaces can be adapted to a dictionary");
+ }
+
+ Type adapterType;
+ if (interfaceToAdapter.TryGetValue(type, out adapterType) == false)
+ {
+ lock (typesDictionaryLocker)
+ {
+ if (interfaceToAdapter.TryGetValue(type, out adapterType) == false)
+ {
+ var appDomain = Thread.GetDomain();
+ var adapterAssemblyName = GetAdapterAssemblyName(type);
+ var typeBuilder = CreateTypeBuilder(type, appDomain, adapterAssemblyName);
+ var adapterAssembly = CreateAdapterAssembly(type, typeBuilder, descriptor);
+ adapterType = CreateAdapterType(type, adapterAssembly);
+ interfaceToAdapter[type] = adapterType;
+ }
+ }
+ }
+
+ return adapterType;
+ }
+
+ private object InternalGetAdapter(Type type, IDictionary dictionary, PropertyDescriptor descriptor)
+ {
+ var adapterType = InternalGetAdapterType(type, descriptor);
+ return CreateAdapterInstance(dictionary, descriptor, adapterType);
+ }
+
+ #region Dynamic Type Generation
+
+ private static TypeBuilder CreateTypeBuilder(Type type, AppDomain appDomain, String adapterAssemblyName)
+ {
+ var assemblyName = new AssemblyName(adapterAssemblyName);
+ var assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+ var moduleBuilder = assemblyBuilder.DefineDynamicModule(adapterAssemblyName);
+ return CreateAdapterType(type, moduleBuilder);
+ }
+
+ private static TypeBuilder CreateAdapterType(Type type, ModuleBuilder moduleBuilder)
+ {
+ var typeBuilder = moduleBuilder.DefineType(GetAdapterFullTypeName(type),
+ TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.BeforeFieldInit);
+ typeBuilder.AddInterfaceImplementation(type);
+ typeBuilder.SetParent(typeof(DictionaryAdapterBase));
+
+ var attribCtorParams = new[] { typeof(Type) };
+ var attribCtorInfo = typeof(DictionaryAdapterAttribute).GetConstructor(attribCtorParams);
+ var attribBuilder = new CustomAttributeBuilder(attribCtorInfo, new[] { type });
+ typeBuilder.SetCustomAttribute(attribBuilder);
+
+ var debugAttribCtorParams = new[] { typeof(string) };
+ var debugAttribCtorInfo = typeof(DebuggerDisplayAttribute).GetConstructor(debugAttribCtorParams);
+ var debugAttribBuilder = new CustomAttributeBuilder(debugAttribCtorInfo, new[] { "Type: {Meta.Type.FullName,nq}" });
+ typeBuilder.SetCustomAttribute(debugAttribBuilder);
+
+ return typeBuilder;
+ }
+
+ private Assembly CreateAdapterAssembly(Type type, TypeBuilder typeBuilder, PropertyDescriptor descriptor)
+ {
+ var binding = FieldAttributes.Public | FieldAttributes.Static;
+ var metaField = typeBuilder.DefineField("__meta", typeof(DictionaryAdapterMeta), binding);
+
+ CreateAdapterConstructor(typeBuilder);
+
+ object[] behaviors;
+ IDictionaryInitializer[] initializers;
+ IDictionaryMetaInitializer[] metaInitializers;
+ var propertyMap = GetPropertyDescriptors(type, out initializers, out metaInitializers, out behaviors);
+
+ CreateMetaProperty(typeBuilder, AdapterGetMeta, metaField);
+
+ foreach (var property in propertyMap)
+ {
+ CreateAdapterProperty(typeBuilder, property.Value);
+ }
+
+ var adapterType = typeBuilder.CreateType();
+ var metaBindings = BindingFlags.Public | BindingFlags.Static | BindingFlags.SetField;
+ var meta = new DictionaryAdapterMeta(type, initializers, metaInitializers, behaviors,
+ propertyMap, descriptor as DictionaryDescriptor, this);
+ adapterType.InvokeMember("__meta", metaBindings, null, null, new[] { meta });
+
+ return typeBuilder.Assembly;
+ }
+
+ #endregion
+
+ #region CreateAdapterConstructor
+
+ private static void CreateAdapterConstructor(TypeBuilder typeBuilder)
+ {
+ var constructorBuilder = typeBuilder.DefineConstructor(
+ MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.Standard,
+ new [] { typeof(DictionaryAdapterInstance) }
+ );
+
+ var ilGenerator = constructorBuilder.GetILGenerator();
+
+ var baseType = typeof(DictionaryAdapterBase);
+ var baseConstructorInfo = baseType.GetConstructors()[0];
+
+ ilGenerator.Emit(OpCodes.Ldarg_0);
+ ilGenerator.Emit(OpCodes.Ldarg_1);
+ ilGenerator.Emit(OpCodes.Call, baseConstructorInfo);
+ ilGenerator.Emit(OpCodes.Ret);
+ }
+
+ #endregion
+
+ #region CreateDictionaryAdapterMeta
+
+ private static void CreateMetaProperty(TypeBuilder typeBuilder, PropertyInfo prop, FieldInfo field)
+ {
+ var propAttribs = MethodAttributes.Public | MethodAttributes.SpecialName |
+ MethodAttributes.HideBySig | MethodAttributes.ReuseSlot |
+ MethodAttributes.Virtual | MethodAttributes.Final;
+
+ var getMethodBuilder = typeBuilder.DefineMethod("get_" + prop.Name,
+ propAttribs, prop.PropertyType, null);
+
+ var getILGenerator = getMethodBuilder.GetILGenerator();
+ if (field.IsStatic)
+ {
+ getILGenerator.Emit(OpCodes.Ldsfld, field);
+ }
+ else
+ {
+ getILGenerator.Emit(OpCodes.Ldarg_0);
+ getILGenerator.Emit(OpCodes.Ldfld, field);
+ }
+ getILGenerator.Emit(OpCodes.Ret);
+
+ typeBuilder.DefineMethodOverride(getMethodBuilder, prop.GetGetMethod());
+ }
+
+ #endregion
+
+ #region CreateAdapterProperty
+
+ private static void CreateAdapterProperty(TypeBuilder typeBuilder, PropertyDescriptor descriptor)
+ {
+ var property = descriptor.Property;
+ var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes, property.PropertyType, null);
+
+ var propAttribs = MethodAttributes.Public | MethodAttributes.SpecialName |
+ MethodAttributes.HideBySig | MethodAttributes.Virtual;
+
+ if (property.CanRead)
+ {
+ CreatePropertyGetMethod(typeBuilder, propertyBuilder, descriptor, propAttribs);
+ }
+
+ if (property.CanWrite)
+ {
+ CreatePropertySetMethod(typeBuilder, propertyBuilder, descriptor, propAttribs);
+ }
+ }
+
+ private static void PreparePropertyMethod(PropertyDescriptor descriptor, ILGenerator propILGenerator)
+ {
+ propILGenerator.DeclareLocal(typeof(String));
+ propILGenerator.DeclareLocal(typeof(object));
+
+ // key = propertyInfo.Name
+ propILGenerator.Emit(OpCodes.Ldstr, descriptor.PropertyName);
+ propILGenerator.Emit(OpCodes.Stloc_0);
+ }
+
+ #endregion
+
+ #region CreatePropertyGetMethod
+
+ private static void CreatePropertyGetMethod(TypeBuilder typeBuilder, PropertyBuilder propertyBuilder,
+ PropertyDescriptor descriptor, MethodAttributes propAttribs)
+ {
+ var getMethodBuilder = typeBuilder.DefineMethod(
+ "get_" + descriptor.PropertyName, propAttribs, descriptor.PropertyType, null);
+
+ var getILGenerator = getMethodBuilder.GetILGenerator();
+
+ var returnDefault = getILGenerator.DefineLabel();
+ var storeResult = getILGenerator.DefineLabel();
+ var loadResult = getILGenerator.DefineLabel();
+
+ PreparePropertyMethod(descriptor, getILGenerator);
+
+ var result = getILGenerator.DeclareLocal(descriptor.PropertyType);
+
+ // value = GetProperty(key, false)
+ getILGenerator.Emit(OpCodes.Ldarg_0);
+ getILGenerator.Emit(OpCodes.Ldloc_0);
+ getILGenerator.Emit(OpCodes.Ldc_I4_0);
+ getILGenerator.Emit(OpCodes.Callvirt, AdapterGetProperty);
+ getILGenerator.Emit(OpCodes.Stloc_1);
+
+ // if (value == null) return null
+ getILGenerator.Emit(OpCodes.Ldloc_1);
+ getILGenerator.Emit(OpCodes.Brfalse_S, returnDefault);
+
+ // return (propertyInfo.PropertyType) value
+ getILGenerator.Emit(OpCodes.Ldloc_1);
+ getILGenerator.Emit(OpCodes.Unbox_Any, descriptor.PropertyType);
+ getILGenerator.Emit(OpCodes.Br_S, storeResult);
+
+ getILGenerator.MarkLabel(returnDefault);
+ getILGenerator.Emit(OpCodes.Ldloca_S, result);
+ getILGenerator.Emit(OpCodes.Initobj, descriptor.PropertyType);
+ getILGenerator.Emit(OpCodes.Br_S, loadResult);
+
+ getILGenerator.MarkLabel(storeResult);
+ getILGenerator.Emit(OpCodes.Stloc_S, result);
+
+ getILGenerator.MarkLabel(loadResult);
+ getILGenerator.Emit(OpCodes.Ldloc_S, result);
+
+ getILGenerator.Emit(OpCodes.Ret);
+
+ propertyBuilder.SetGetMethod(getMethodBuilder);
+ }
+
+ #endregion
+
+ #region CreatePropertySetMethod
+
+ private static void CreatePropertySetMethod(TypeBuilder typeBuilder, PropertyBuilder propertyBuilder,
+ PropertyDescriptor descriptor, MethodAttributes propAttribs)
+ {
+ var setMethodBuilder = typeBuilder.DefineMethod(
+ "set_" + descriptor.PropertyName, propAttribs, null, new[] {descriptor.PropertyType});
+
+ var setILGenerator = setMethodBuilder.GetILGenerator();
+ PreparePropertyMethod(descriptor, setILGenerator);
+
+ setILGenerator.Emit(OpCodes.Ldarg_1);
+ if (descriptor.PropertyType.IsValueType)
+ {
+ setILGenerator.Emit(OpCodes.Box, descriptor.PropertyType);
+ }
+ setILGenerator.Emit(OpCodes.Stloc_1);
+
+ // ignore = SetProperty(key, ref value)
+ setILGenerator.Emit(OpCodes.Ldarg_0);
+ setILGenerator.Emit(OpCodes.Ldloc_0);
+ setILGenerator.Emit(OpCodes.Ldloca_S, 1);
+ setILGenerator.Emit(OpCodes.Callvirt, AdapterSetProperty);
+ setILGenerator.Emit(OpCodes.Pop);
+ setILGenerator.Emit(OpCodes.Ret);
+
+ propertyBuilder.SetSetMethod(setMethodBuilder);
+ }
+
+ #endregion
+
+ #region Property Descriptors
+
+ private static Dictionary GetPropertyDescriptors(
+ Type type, out IDictionaryInitializer[] typeInitializers,
+ out IDictionaryMetaInitializer[] metaInitializers, out object[] typeBehaviors)
+ {
+ var propertyMap = new Dictionary();
+ var interfaceBehaviors = typeBehaviors = ExpandBehaviors(GetInterfaceBehaviors(type)).ToArray();
+
+ typeInitializers = typeBehaviors.OfType().Prioritize().ToArray();
+ metaInitializers = typeBehaviors.OfType().Prioritize().ToArray();
+ var defaultFetch = typeBehaviors.OfType().Select(b => b.Fetch).FirstOrDefault();
+
+ CollectProperties(type, property =>
+ {
+ var propertyBehaviors = ExpandBehaviors(GetPropertyBehaviors(property)).ToArray();
+ var propertyDescriptor = new PropertyDescriptor(property, propertyBehaviors);
+
+ var descriptorInitializers = propertyBehaviors.OfType();
+ foreach (var descriptorInitializer in descriptorInitializers.OrderBy(b => b.ExecutionOrder))
+ {
+ descriptorInitializer.Initialize(propertyDescriptor, propertyBehaviors);
+ }
+
+ propertyDescriptor.AddKeyBuilders(
+ propertyBehaviors.OfType().Prioritize(
+ GetInterfaceBehaviors(property.ReflectedType))
+ );
+
+ propertyDescriptor.AddGetters(
+ propertyBehaviors.OfType().Prioritize(
+ interfaceBehaviors.OfType())
+ );
+ AddDefaultGetter(propertyDescriptor);
+
+ propertyDescriptor.AddSetters(
+ propertyBehaviors.OfType().Prioritize(
+ interfaceBehaviors.OfType())
+ );
+
+ bool? propertyFetch = (from b in propertyBehaviors.OfType() select b.Fetch).FirstOrDefault();
+ propertyDescriptor.Fetch = propertyFetch.GetValueOrDefault(defaultFetch);
+
+ PropertyDescriptor existingDescriptor;
+ if (propertyMap.TryGetValue(property.Name, out existingDescriptor))
+ {
+ var existingProperty = existingDescriptor.Property;
+ if (existingProperty.PropertyType == property.PropertyType)
+ {
+ if (property.CanRead && property.CanWrite)
+ {
+ propertyMap[property.Name] = propertyDescriptor;
+ }
+ return;
+ }
+ }
+
+ propertyMap.Add(property.Name, propertyDescriptor);
+ });
+
+ return propertyMap;
+ }
+
+ private static IEnumerable GetInterfaceBehaviors(Type type) where T : class
+ {
+ return AttributesUtil.GetTypeAttributes(type);
+ }
+
+ private static IEnumerable GetPropertyBehaviors(MemberInfo member) where T : class
+ {
+ return AttributesUtil.GetAttributes(member);
+ }
+
+ private static IEnumerable ExpandBehaviors(IEnumerable behaviors)
+ {
+ return behaviors.SelectMany(behavior =>
+ {
+ if (behavior is IDictionaryBehaviorBuilder)
+ return ((IDictionaryBehaviorBuilder)behavior).BuildBehaviors().Cast();
+ return Enumerable.Repeat(behavior, 1);
+ });
+ }
+
+ private static void CollectProperties(Type currentType, Action onProperty)
+ {
+ var types = new List();
+ types.Add(currentType);
+ types.AddRange(currentType.GetInterfaces());
+ var publicBindings = BindingFlags.Public | BindingFlags.Instance;
+
+ foreach (Type type in types)
+ {
+ if (!InfrastructureTypes.Contains(type))
+ {
+ foreach (var property in type.GetProperties(publicBindings))
+ {
+ onProperty(property);
+ }
+ }
+ }
+ }
+
+ private static void AddDefaultGetter(PropertyDescriptor descriptor)
+ {
+ if (descriptor.TypeConverter != null)
+ {
+ descriptor.AddGetter(new DefaultPropertyGetter(descriptor.TypeConverter));
+ }
+ }
+
+ private static readonly ICollection InfrastructureTypes =
+#if SL3 //Silverlight 3 does not have HashSet
+ new List
+#else
+ new HashSet
+#endif
+ {
+ typeof (IEditableObject),
+ typeof (IDictionaryEdit),
+ typeof (IChangeTracking),
+ typeof (IRevertibleChangeTracking),
+ typeof (IDictionaryNotify),
+ typeof (IDataErrorInfo),
+ typeof (IDictionaryValidate),
+ typeof (IDictionaryAdapter)
+ };
+
+ #endregion
+
+ #region Assembly Support
+
+ private string GetAdapterAssemblyName(Type type)
+ {
+#if SILVERLIGHT
+ string assemblyName;
+ var commaLocation = type.Assembly.FullName.IndexOf(',');
+ if(commaLocation>-1)
+ {
+ assemblyName = type.Assembly.FullName.Substring(0, commaLocation);
+ }
+ else
+ {
+ assemblyName = "UnnamedAssembly";
+ }
+#else
+ var assemblyName = type.Assembly.GetName().Name;
+#endif
+ var safeTypeFullName = GetSafeTypeFullName(type);
+ return string.Concat(assemblyName, ".", safeTypeFullName, ".DictionaryAdapter");
+ }
+
+ private static String GetAdapterFullTypeName(Type type)
+ {
+ return type.Namespace + "." + GetAdapterTypeName(type);
+ }
+
+ private static String GetAdapterTypeName(Type type)
+ {
+ return GetSafeTypeName(type).Substring(1) + "DictionaryAdapter";
+ }
+
+ public static string GetSafeTypeFullName(Type type)
+ {
+ if (type.IsGenericTypeDefinition)
+ {
+ return type.FullName.Replace("`", "_");
+ }
+
+ if (type.IsGenericType)
+ {
+ var name = new StringBuilder();
+ if (!string.IsNullOrEmpty(type.Namespace))
+ {
+ name.Append(type.Namespace).Append(".");
+ }
+
+ AppendGenericTypeName(type, name);
+ return name.ToString();
+ }
+
+ return type.FullName;
+ }
+
+ public static string GetSafeTypeName(Type type)
+ {
+ if (type.IsGenericTypeDefinition)
+ {
+ return type.Name.Replace("`", "_");
+ }
+
+ if (type.IsGenericType)
+ {
+ var name = new StringBuilder();
+ AppendGenericTypeName(type, name);
+ return name.ToString();
+ }
+
+ return type.Name;
+ }
+
+ private static void AppendGenericTypeName(Type type, StringBuilder sb)
+ {
+ // Replace back tick preceding parameter count with _ List`1 => List_1
+ sb.Append(type.Name.Replace("`", "_"));
+
+ // Append safe full name of each type argument, separated by _
+ foreach (var argument in type.GetGenericArguments())
+ {
+ sb.Append("_").Append(GetSafeTypeFullName(argument).Replace(".", "_"));
+ }
+ }
+
+ private static Type CreateAdapterType(Type type, Assembly assembly)
+ {
+ var adapterFullTypeName = GetAdapterFullTypeName(type);
+ return assembly.GetType(adapterFullTypeName, true);
+ }
+
+ private object CreateAdapterInstance(IDictionary dictionary, PropertyDescriptor descriptor, Type adapterType)
+ {
+ var metaBindings = BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField;
+ var meta = (DictionaryAdapterMeta)adapterType.InvokeMember("__meta", metaBindings, null, null, null);
+ var instance = new DictionaryAdapterInstance(dictionary, meta, descriptor, this);
+ return Activator.CreateInstance(adapterType, instance);
+ }
+
+ #endregion
+
+ #region Reflection Cache
+
+ private static readonly PropertyInfo AdapterGetMeta =
+ typeof(IDictionaryAdapter).GetProperty("Meta");
+
+ private static readonly MethodInfo AdapterGetProperty =
+ typeof(IDictionaryAdapter).GetMethod("GetProperty");
+
+ private static readonly MethodInfo AdapterSetProperty =
+ typeof(IDictionaryAdapter).GetMethod("SetProperty");
+
+ #endregion
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterInstance.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterInstance.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterInstance.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterInstance.cs Sun Feb 13 19:28:42 2011
@@ -0,0 +1,91 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ internal class DictionaryAdapterInstance
+ {
+ private IDictionary extendedProperties;
+
+ public DictionaryAdapterInstance(IDictionary dictionary, DictionaryAdapterMeta meta,
+ PropertyDescriptor descriptor, IDictionaryAdapterFactory factory)
+ {
+ Dictionary = dictionary;
+ Descriptor = descriptor;
+ Factory = factory;
+
+ Properties = meta.Properties;
+ Initializers = meta.Initializers;
+ MergeBehaviorOverrides(meta);
+ }
+
+ internal int? OldHashCode { get; set; }
+
+ public IDictionary Dictionary { get; private set; }
+
+ public PropertyDescriptor Descriptor { get; private set; }
+
+ public IDictionaryAdapterFactory Factory { get; private set; }
+
+ public IDictionaryInitializer[] Initializers { get; private set; }
+
+ public IDictionary Properties { get; private set; }
+
+ public IDictionaryEqualityHashCodeStrategy EqualityHashCodeStrategy { get; set; }
+
+ public IDictionaryCreateStrategy CreateStrategy { get; set; }
+
+ public IDictionary ExtendedProperties
+ {
+ get
+ {
+ if (extendedProperties == null)
+ {
+ extendedProperties = new Dictionary();
+ }
+ return extendedProperties;
+ }
+ }
+
+ private void MergeBehaviorOverrides(DictionaryAdapterMeta meta)
+ {
+ if (Descriptor == null) return;
+
+ var typeDescriptor = Descriptor as DictionaryDescriptor;
+
+ if (typeDescriptor != null)
+ {
+ Initializers = Initializers.Prioritize(typeDescriptor.Initializers).ToArray();
+ }
+
+ Properties = new Dictionary();
+
+ foreach (var property in meta.Properties)
+ {
+ var propertyDescriptor = property.Value;
+
+ var propertyOverride = new PropertyDescriptor(propertyDescriptor, false)
+ .AddKeyBuilders(propertyDescriptor.KeyBuilders.Prioritize(Descriptor.KeyBuilders))
+ .AddGetters(propertyDescriptor.Getters.Prioritize(Descriptor.Getters))
+ .AddSetters(propertyDescriptor.Setters.Prioritize(Descriptor.Setters));
+
+ Properties.Add(property.Key, propertyOverride);
+ }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterMeta.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterMeta.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterMeta.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryAdapterMeta.cs Sun Feb 13 19:28:47 2011
@@ -0,0 +1,77 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+
+ [DebuggerDisplay("Type: {Type.FullName,nq}")]
+ internal class DictionaryAdapterMeta
+ {
+ private IDictionary extendedProperties;
+
+ public DictionaryAdapterMeta(Type type, IDictionaryInitializer[] initializers,
+ IDictionaryMetaInitializer[] metaInitializers,
+ object[] behaviors, IDictionary properties,
+ DictionaryDescriptor descriptor, IDictionaryAdapterFactory factory)
+ {
+ Type = type;
+ Initializers = initializers;
+ MetaInitializers = metaInitializers;
+ Behaviors = behaviors;
+ Properties = properties;
+
+ InitializeMeta(factory, descriptor);
+ }
+
+ public Type Type { get; private set; }
+
+ public object[] Behaviors { get; private set; }
+
+ public IDictionaryInitializer[] Initializers { get; private set; }
+
+ public IDictionaryMetaInitializer[] MetaInitializers { get; private set; }
+
+ public IDictionary Properties { get; private set; }
+
+ public IDictionary ExtendedProperties
+ {
+ get
+ {
+ if (extendedProperties == null)
+ {
+ extendedProperties = new Dictionary();
+ }
+ return extendedProperties;
+ }
+ }
+
+ private void InitializeMeta(IDictionaryAdapterFactory factory, DictionaryDescriptor descriptor)
+ {
+ if (descriptor != null)
+ {
+ MetaInitializers = MetaInitializers.Prioritize(descriptor.MetaInitializers).ToArray();
+ }
+
+ foreach (var metaInitializer in MetaInitializers)
+ {
+ metaInitializer.Initialize(factory, this);
+ }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryDescriptor.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryDescriptor.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryDescriptor.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryDescriptor.cs Sun Feb 13 19:28:53 2011
@@ -0,0 +1,205 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Linq;
+ using System.Collections.Generic;
+ using System.Reflection;
+
+ internal class DictionaryDescriptor : PropertyDescriptor
+ {
+ private List initializers;
+ private List metaInitializers;
+
+ private static readonly ICollection NoInitializers = new IDictionaryInitializer[0];
+ private static readonly ICollection NoMetaInitializers = new IDictionaryMetaInitializer[0];
+
+ public DictionaryDescriptor()
+ {
+ }
+
+ public DictionaryDescriptor(PropertyInfo property, object[] behaviors)
+ : base(property, behaviors)
+ {
+ }
+
+ ///
+ /// Gets the initializers.
+ ///
+ /// The initializers.
+ public ICollection Initializers
+ {
+ get { return initializers ?? NoInitializers; }
+ }
+
+ ///
+ /// Gets the meta-data initializers.
+ ///
+ /// The meta-data initializers.
+ public ICollection MetaInitializers
+ {
+ get { return metaInitializers ?? NoMetaInitializers; }
+ }
+
+ ///
+ /// Adds the dictionary initializers.
+ ///
+ /// The initializers.
+ public DictionaryDescriptor AddInitializer(params IDictionaryInitializer[] inits)
+ {
+ return AddInitializers((IEnumerable)inits);
+ }
+
+ ///
+ /// Adds the dictionary initializers.
+ ///
+ /// The initializers.
+ public DictionaryDescriptor AddInitializers(IEnumerable inits)
+ {
+ if (inits != null)
+ {
+ if (initializers == null)
+ {
+ initializers = new List(inits);
+ }
+ else
+ {
+ initializers.AddRange(inits);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the initializers to the other
+ ///
+ ///
+ ///
+ public DictionaryDescriptor CopyInitializers(DictionaryDescriptor other)
+ {
+ if (initializers != null)
+ {
+ other.AddInitializers(initializers);
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the filtered initializers to the other
+ ///
+ ///
+ ///
+ ///
+ public DictionaryDescriptor CopyInitializers(DictionaryDescriptor other, Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ if (initializers != null)
+ {
+ other.AddInitializers(initializers.Where(selector));
+ }
+ return this;
+ }
+
+ ///
+ /// Adds the dictionary meta-data initializers.
+ ///
+ /// The meta-data initializers.
+ public DictionaryDescriptor AddMetaInitializer(params IDictionaryMetaInitializer[] inits)
+ {
+ return AddMetaInitializers((IEnumerable)inits);
+ }
+
+ ///
+ /// Adds the dictionary meta-data initializers.
+ ///
+ /// The meta-data initializers.
+ public DictionaryDescriptor AddMetaInitializers(IEnumerable inits)
+ {
+ if (inits != null)
+ {
+ if (metaInitializers == null)
+ {
+ metaInitializers = new List(inits);
+ }
+ else
+ {
+ metaInitializers.AddRange(inits);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the meta-initializers to the other
+ ///
+ ///
+ ///
+ public DictionaryDescriptor CopyMetaInitializers(DictionaryDescriptor other)
+ {
+ if (metaInitializers != null)
+ {
+ other.AddMetaInitializers(metaInitializers);
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the filtered meta-initializers to the other
+ ///
+ ///
+ ///
+ ///
+ public DictionaryDescriptor CopyMetaInitializers(DictionaryDescriptor other,
+ Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ if (metaInitializers != null)
+ {
+ other.AddMetaInitializers(metaInitializers.Where(selector));
+ }
+ return this;
+ }
+
+ public override PropertyDescriptor CopyBehaviors(PropertyDescriptor other)
+ {
+ if (other is DictionaryDescriptor)
+ {
+ var otherDict = (DictionaryDescriptor)other;
+ CopyMetaInitializers(otherDict).CopyInitializers(otherDict);
+ }
+ return base.CopyBehaviors(other);
+ }
+
+ protected override void InternalAddBehavior(IDictionaryBehavior behavior)
+ {
+ if (behavior is IDictionaryInitializer)
+ {
+ AddInitializer((IDictionaryInitializer)behavior);
+ }
+ if (behavior is IDictionaryMetaInitializer)
+ {
+ AddMetaInitializer((IDictionaryMetaInitializer)behavior);
+ }
+ base.InternalAddBehavior(behavior);
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryValidateGroup.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryValidateGroup.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryValidateGroup.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\DictionaryValidateGroup.cs Sun Feb 13 19:28:59 2011
@@ -0,0 +1,106 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Linq;
+
+ internal class DictionaryValidateGroup : IDictionaryValidate, INotifyPropertyChanged, IDisposable
+ {
+ private readonly object[] groups;
+ private readonly IDictionaryAdapter adapter;
+ private readonly string[] propertyNames;
+ private readonly PropertyChangedEventHandler propertyChanged;
+
+ public DictionaryValidateGroup(object[] groups, IDictionaryAdapter adapter)
+ {
+ this.groups = groups;
+ this.adapter = adapter;
+
+ propertyNames = (from property in this.adapter.This.Properties.Values
+ from groupings in property.Behaviors.OfType()
+ where this.groups.Intersect(groupings.Group).Any()
+ select property.PropertyName).Distinct().ToArray();
+
+ if (propertyNames.Length > 0 && adapter.CanNotify)
+ {
+ propertyChanged += (sender, args) =>
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, args);
+ };
+ this.adapter.PropertyChanged += propertyChanged;
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public bool CanValidate
+ {
+ get { return adapter.CanValidate; }
+ set { adapter.CanValidate = value; }
+ }
+
+ public bool IsValid
+ {
+ get { return string.IsNullOrEmpty(Error); }
+ }
+
+ public string Error
+ {
+ get
+ {
+ return string.Join(Environment.NewLine,
+ propertyNames.Select(propertyName => adapter[propertyName])
+ .Where(errors => !string.IsNullOrEmpty(errors)).ToArray());
+ }
+ }
+
+ public string this[string columnName]
+ {
+ get
+ {
+ if (Array.IndexOf(propertyNames, columnName) >= 0)
+ {
+ return adapter[columnName];
+ }
+ return string.Empty;
+ }
+ }
+
+ public DictionaryValidateGroup ValidateGroups(params object[] groups)
+ {
+ groups = this.groups.Union(groups).ToArray();
+ return new DictionaryValidateGroup(groups, adapter);
+ }
+
+ public IEnumerable Validators
+ {
+ get { return adapter.Validators; }
+ }
+
+ public void AddValidator(IDictionaryValidator validator)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Dispose()
+ {
+ adapter.PropertyChanged -= propertyChanged;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\GenericDictionaryAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\GenericDictionaryAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\GenericDictionaryAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\GenericDictionaryAdapter.cs Sun Feb 13 19:35:08 2011
@@ -0,0 +1,62 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License";
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+
+ internal class GenericDictionaryAdapter : AbstractDictionaryAdapter
+ {
+ private readonly IDictionary dictionary;
+
+ public GenericDictionaryAdapter(IDictionary dictionary)
+ {
+ this.dictionary = dictionary;
+ }
+
+ public override bool IsReadOnly
+ {
+ get { return dictionary.IsReadOnly; }
+ }
+
+ public override bool Contains(object key)
+ {
+ return dictionary.Keys.Contains(GetKey(key));
+ }
+
+ public override object this[object key]
+ {
+ get { return dictionary[GetKey(key)]; }
+ set { dictionary[GetKey(key)] = (TValue)value; }
+ }
+
+ private static string GetKey(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ return key.ToString();
+ }
+ }
+
+ internal static class GenericDictionaryAdapter
+ {
+ public static GenericDictionaryAdapter ForDictionaryAdapter(this IDictionary dictionary)
+ {
+ return new GenericDictionaryAdapter(dictionary);
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapter.cs Sun Feb 13 19:29:10 2011
@@ -0,0 +1,48 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Contract for manipulating the Dictionary adapter.
+ ///
+ internal interface IDictionaryAdapter : IDictionaryEdit, IDictionaryNotify, IDictionaryValidate, IDictionaryCreate
+ {
+ DictionaryAdapterMeta Meta { get; }
+
+ DictionaryAdapterInstance This { get; }
+
+ string GetKey(string propertyName);
+
+ object GetProperty(string propertyName, bool ifExists);
+
+ object ReadProperty(string key);
+
+ T GetPropertyOfType(string propertyName);
+
+ bool SetProperty(string propertyName, ref object value);
+
+ void StoreProperty(PropertyDescriptor property, string key, object value);
+
+ void ClearProperty(PropertyDescriptor property, string key);
+
+ void CopyTo(IDictionaryAdapter other);
+
+ void CopyTo(IDictionaryAdapter other, Predicate selector);
+
+ T Coerce() where T : class;
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterFactory.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterFactory.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterFactory.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterFactory.cs Sun Feb 13 19:29:15 2011
@@ -0,0 +1,125 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+#if !SILVERLIGHT
+ using System.Collections.Specialized;
+ using System.Xml.XPath;
+#endif
+
+ ///
+ /// Defines the contract for building typed dictionary adapters.
+ ///
+ internal interface IDictionaryAdapterFactory
+ {
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the dictionary.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ T GetAdapter(IDictionary dictionary);
+
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the dictionary.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ object GetAdapter(Type type, IDictionary dictionary);
+
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// The property descriptor.
+ /// An implementation of the typed interface bound to the dictionary.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ object GetAdapter(Type type, IDictionary dictionary, PropertyDescriptor descriptor);
+
+#if !SILVERLIGHT
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the namedValues.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ T GetAdapter(NameValueCollection nameValues);
+
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the namedValues.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ object GetAdapter(Type type, NameValueCollection nameValues);
+
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the xpath navigable.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ T GetAdapter(IXPathNavigable xpathNavigable);
+
+ ///
+ /// Gets a typed adapter bound to the .
+ ///
+ /// The typed interface.
+ /// The underlying source of properties.
+ /// An implementation of the typed interface bound to the xpath navigable.
+ ///
+ /// The type represented by T must be an interface with properties.
+ ///
+ object GetAdapter(Type type, IXPathNavigable xpathNavigable);
+#endif
+
+ ///
+ /// Gets the associated with the type.
+ ///
+ /// The typed interface.
+ /// The adapter meta-data.
+ DictionaryAdapterMeta GetAdapterMeta(Type type);
+
+ ///
+ /// Gets the associated with the type.
+ ///
+ /// The typed interface.
+ /// The property descriptor.
+ /// The adapter meta-data.
+ DictionaryAdapterMeta GetAdapterMeta(Type type, PropertyDescriptor descriptor);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterVisitor.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterVisitor.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterVisitor.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryAdapterVisitor.cs Sun Feb 13 19:29:20 2011
@@ -0,0 +1,33 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ ///
+ /// Conract for traversing a .
+ ///
+ internal interface IDictionaryAdapterVisitor
+ {
+ void VisitDictionaryAdapter(IDictionaryAdapter dictionaryAdapter);
+
+ void VisitProperty(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property);
+
+ void VisitInterface(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property);
+
+ void VisitCollection(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property,
+ Type collectionItemType);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehavior.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehavior.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehavior.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehavior.cs Sun Feb 13 19:29:26 2011
@@ -0,0 +1,27 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Defines the contract for customizing dictionary access.
+ ///
+ internal interface IDictionaryBehavior
+ {
+ ///
+ /// Determines relative order to apply related behaviors.
+ ///
+ int ExecutionOrder { get; }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehaviorBuilder.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehaviorBuilder.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehaviorBuilder.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryBehaviorBuilder.cs Sun Feb 13 19:29:32 2011
@@ -0,0 +1,30 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Defines the contract for building s.
+ ///
+ internal interface IDictionaryBehaviorBuilder
+ {
+ ///
+ /// Builds the dictionary behaviors.
+ ///
+ ///
+ IEnumerable BuildBehaviors();
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreate.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreate.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreate.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreate.cs Sun Feb 13 19:29:38 2011
@@ -0,0 +1,37 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Contract for creating additional Dictionary adapters.
+ ///
+ internal interface IDictionaryCreate
+ {
+ T Create();
+
+ object Create(Type type);
+
+ T Create(IDictionary dictionary);
+
+ object Create(Type type, IDictionary dictionary);
+
+ T Create(Action init);
+
+ T Create(IDictionary dictionary, Action init);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreateStrategy.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreateStrategy.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreateStrategy.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryCreateStrategy.cs Sun Feb 13 19:29:51 2011
@@ -0,0 +1,24 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ internal interface IDictionaryCreateStrategy
+ {
+ object Create(IDictionaryAdapter adapter, Type type, IDictionary dictionary);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEdit.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEdit.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEdit.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEdit.cs Sun Feb 13 19:29:57 2011
@@ -0,0 +1,37 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.ComponentModel;
+
+ ///
+ /// Contract for editing the Dictionary adapter.
+ ///
+ internal interface IDictionaryEdit : IEditableObject, IRevertibleChangeTracking
+ {
+ bool CanEdit { get; }
+
+ bool IsEditing { get; }
+
+ bool SupportsMultiLevelEdit { get; set; }
+
+ IDisposable SuppressEditingBlock();
+
+ void SuppressEditing();
+
+ void ResumeEditing();
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEqualityHashCodeStrategy.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEqualityHashCodeStrategy.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEqualityHashCodeStrategy.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryEqualityHashCodeStrategy.cs Sun Feb 13 19:30:02 2011
@@ -0,0 +1,23 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ internal interface IDictionaryEqualityHashCodeStrategy
+ {
+ bool Equals(IDictionaryAdapter adapter1, IDictionaryAdapter adapter2);
+
+ bool GetHashCode(IDictionaryAdapter adapter, out int hashCode);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryInitializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryInitializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryInitializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryInitializer.cs Sun Feb 13 19:30:09 2011
@@ -0,0 +1,29 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Contract for dictionary initialization.
+ ///
+ internal interface IDictionaryInitializer : IDictionaryBehavior
+ {
+ ///
+ /// Performs any initialization of the
+ ///
+ /// The dictionary adapter.
+ /// The dictionary behaviors.
+ void Initialize(IDictionaryAdapter dictionaryAdapter, object[] behaviors);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryKeyBuilder.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryKeyBuilder.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryKeyBuilder.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryKeyBuilder.cs Sun Feb 13 19:30:14 2011
@@ -0,0 +1,34 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// Defines the contract for building typed dictionary keys.
+ ///
+ internal interface IDictionaryKeyBuilder : IDictionaryBehavior
+ {
+ ///
+ /// Builds the specified key.
+ ///
+ /// The dictionary adapter.
+ /// The current key.
+ /// The property.
+ /// The updated key
+ String GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property);
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryMetaInitializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryMetaInitializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryMetaInitializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryMetaInitializer.cs Sun Feb 13 19:30:20 2011
@@ -0,0 +1,30 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Contract for dictionary meta-data initialization.
+ ///
+ internal interface IDictionaryMetaInitializer : IDictionaryBehavior
+ {
+ ///
+ /// Performs any initialization of the dictionary adapter meta-data.
+ ///
+ /// The dictionary adapter factory.
+ /// The dictionary adapter meta.
+ ///
+ void Initialize(IDictionaryAdapterFactory factory, DictionaryAdapterMeta dictionaryMeta);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryNotify.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryNotify.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryNotify.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryNotify.cs Sun Feb 13 20:03:05 2011
@@ -0,0 +1,81 @@
+// Copyright 2004-2010 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.ComponentModel;
+
+ #region Class PropertyModifiedEventArgs
+
+ internal class PropertyModifiedEventArgs : PropertyChangedEventArgs
+ {
+ public PropertyModifiedEventArgs(String propertyName, object oldPropertyValue, object newPropertyValue)
+ : base(propertyName)
+ {
+ OldPropertyValue = oldPropertyValue;
+ NewPropertyValue = newPropertyValue;
+ }
+
+ public object OldPropertyValue { get; private set; }
+
+ public object NewPropertyValue { get; private set; }
+ }
+
+ #endregion
+
+ #region Class PropertyModifyingEventArgs
+
+ internal class PropertyModifyingEventArgs : PropertyChangingEventArgs
+ {
+ public PropertyModifyingEventArgs(String propertyName, object oldPropertyValue, object newPropertyValue)
+ : base(propertyName)
+ {
+ OldPropertyValue = oldPropertyValue;
+ NewPropertyValue = newPropertyValue;
+ }
+
+ public object OldPropertyValue { get; private set; }
+
+ public object NewPropertyValue { get; private set; }
+
+ public bool Cancel { get; set; }
+ }
+
+ internal delegate void PropertyModifyingEventHandler(object sender, PropertyModifyingEventArgs e);
+
+ #endregion
+
+ ///
+ /// Contract for managing Dictionary adapter notifications.
+ ///
+ internal interface IDictionaryNotify :
+#if !SILVERLIGHT
+ INotifyPropertyChanging,
+#endif
+ INotifyPropertyChanged
+ {
+ bool CanNotify { get; }
+
+ bool ShouldNotify { get; }
+
+ bool PropagateChildNotifications { get; set; }
+
+ IDisposable SuppressNotificationsBlock();
+
+ void SuppressNotifications();
+
+ void ResumeNotifications();
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertyGetter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertyGetter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertyGetter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertyGetter.cs Sun Feb 13 19:30:34 2011
@@ -0,0 +1,36 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections;
+
+ ///
+ /// Defines the contract for retrieving dictionary values.
+ ///
+ internal interface IDictionaryPropertyGetter : IDictionaryBehavior
+ {
+ ///
+ /// Gets the effective dictionary value.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The stored value.
+ /// The property.
+ /// true if return only existing.
+ /// The effective property value.
+ object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key,
+ object storedValue, PropertyDescriptor property, bool ifExists);
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertySetter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertySetter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertySetter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryPropertySetter.cs Sun Feb 13 19:30:38 2011
@@ -0,0 +1,34 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+
+ ///
+ /// Defines the contract for updating dictionary values.
+ ///
+ internal interface IDictionaryPropertySetter : IDictionaryBehavior
+ {
+ ///
+ /// Sets the stored dictionary value.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The stored value.
+ /// The property.
+ /// true if the property should be stored.
+ bool SetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, ref object value,
+ PropertyDescriptor property);
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidate.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidate.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidate.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidate.cs Sun Feb 13 19:30:43 2011
@@ -0,0 +1,35 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections.Generic;
+ using System.ComponentModel;
+
+ ///
+ /// Contract for validating Dictionary adapter.
+ ///
+ internal interface IDictionaryValidate : IDataErrorInfo, INotifyPropertyChanged
+ {
+ bool CanValidate { get; set; }
+
+ bool IsValid { get; }
+
+ DictionaryValidateGroup ValidateGroups(params object[] groups);
+
+ IEnumerable Validators { get; }
+
+ void AddValidator(IDictionaryValidator validator);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidator.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidator.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidator.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IDictionaryValidator.cs Sun Feb 13 19:30:48 2011
@@ -0,0 +1,50 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Contract for dictionary validation.
+ ///
+ internal interface IDictionaryValidator
+ {
+ ///
+ /// Determines if is valid.
+ ///
+ /// The dictionary adapter.
+ /// true if valid.
+ bool IsValid(IDictionaryAdapter dictionaryAdapter);
+
+ ///
+ /// Validates the .
+ ///
+ /// The dictionary adapter.
+ /// The error summary information.
+ string Validate(IDictionaryAdapter dictionaryAdapter);
+
+ ///
+ /// Validates the for a property.
+ ///
+ /// The dictionary adapter.
+ /// The property to validate.
+ /// The property summary information.
+ string Validate(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property);
+
+ ///
+ /// Invalidates any results cached by the validator.
+ ///
+ /// The dictionary adapter.
+ void Invalidate(IDictionaryAdapter dictionaryAdapter);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IPropertyDescriptorInitializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IPropertyDescriptorInitializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IPropertyDescriptorInitializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IPropertyDescriptorInitializer.cs Sun Feb 13 19:30:53 2011
@@ -0,0 +1,29 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Contract for property descriptor initialization.
+ ///
+ internal interface IPropertyDescriptorInitializer : IDictionaryBehavior
+ {
+ ///
+ /// Performs any initialization of the
+ ///
+ /// The property descriptor.
+ /// The property behaviors.
+ void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IXPathSerializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IXPathSerializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\IXPathSerializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\IXPathSerializer.cs Sun Feb 13 19:30:58 2011
@@ -0,0 +1,28 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if !SILVERLIGHT
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Xml.XPath;
+
+ internal interface IXPathSerializer
+ {
+ bool WriteObject(XPathResult result, XPathNavigator node, object value);
+
+ bool ReadObject(XPathResult result, XPathNavigator node, out object value);
+ }
+}
+#endif
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\NameValueCollectionAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\NameValueCollectionAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\NameValueCollectionAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\NameValueCollectionAdapter.cs Sun Feb 13 19:31:04 2011
@@ -0,0 +1,85 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if! SILVERLIGHT
+ using System;
+ using System.Collections.Specialized;
+
+ ///
+ ///
+ ///
+ internal class NameValueCollectionAdapter : AbstractDictionaryAdapter
+ {
+ private readonly NameValueCollection nameValues;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name values.
+ public NameValueCollectionAdapter(NameValueCollection nameValues)
+ {
+ this.nameValues = nameValues;
+ }
+
+ ///
+ /// Gets a value indicating whether the object is read-only.
+ ///
+ ///
+ /// true if the object is read-only; otherwise, false.
+ public override bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Determines whether the object contains an element with the specified key.
+ ///
+ /// The key to locate in the object.
+ ///
+ /// true if the contains an element with the key; otherwise, false.
+ ///
+ /// key is null.
+ public override bool Contains(object key)
+ {
+ return Array.IndexOf(nameValues.AllKeys, key) >= 0;
+ }
+
+ ///
+ /// Gets or sets the with the specified key.
+ ///
+ ///
+ public override object this[object key]
+ {
+ get { return nameValues[key.ToString()]; }
+ set
+ {
+ String val = (value != null) ? value.ToString() : null;
+ nameValues[key.ToString()] = val;
+ }
+ }
+
+ ///
+ /// Adapts the specified name values.
+ ///
+ /// The name values.
+ ///
+ public static NameValueCollectionAdapter Adapt(NameValueCollection nameValues)
+ {
+ return new NameValueCollectionAdapter(nameValues);
+ }
+ }
+#endif
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\PropertyDescriptor.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\PropertyDescriptor.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\PropertyDescriptor.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\PropertyDescriptor.cs Sun Feb 13 19:31:10 2011
@@ -0,0 +1,560 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Linq;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Reflection;
+ using System.Diagnostics;
+
+ using Castle.Core.Internal;
+
+ ///
+ /// Describes a dictionary property.
+ ///
+ [DebuggerDisplay("{Property.DeclaringType.FullName,nq}.{PropertyName,nq}")]
+ internal class PropertyDescriptor : IDictionaryKeyBuilder, IDictionaryPropertyGetter, IDictionaryPropertySetter
+ {
+ private List getters;
+ private List setters;
+ private List keyBuilders;
+ private IDictionary state;
+
+ private static readonly object[] NoBehaviors = new object[0];
+ private static readonly ICollection NoKeysBuilders = new IDictionaryKeyBuilder[0];
+ private static readonly ICollection NoHGetters = new IDictionaryPropertyGetter[0];
+ private static readonly ICollection NoSetters = new IDictionaryPropertySetter[0];
+
+ ///
+ /// Initializes an empty class.
+ ///
+ public PropertyDescriptor()
+ {
+ Behaviors = NoBehaviors;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The property.
+ /// The property behaviors.
+ public PropertyDescriptor(PropertyInfo property, object[] behaviors) : this()
+ {
+ Property = property;
+ Behaviors = behaviors ?? NoBehaviors;
+ IsDynamicProperty = typeof(IDynamicValue).IsAssignableFrom(property.PropertyType);
+ ObtainTypeConverter();
+ }
+
+ ///
+ /// Copies an existinginstance of the class.
+ ///
+ ///
+ ///
+ public PropertyDescriptor(PropertyDescriptor source, bool copyBehaviors)
+ {
+ Property = source.Property;
+ Behaviors = source.Behaviors;
+ IsDynamicProperty = source.IsDynamicProperty;
+ TypeConverter = source.TypeConverter;
+ SuppressNotifications = source.SuppressNotifications;
+ state = source.state;
+ Fetch = source.Fetch;
+
+ if (copyBehaviors)
+ {
+ keyBuilders = source.keyBuilders;
+ getters = source.getters;
+ setters = source.setters;
+ }
+ }
+
+ ///
+ ///
+ ///
+ public int ExecutionOrder
+ {
+ get { return 0; }
+ }
+
+ ///
+ /// Gets the property name.
+ ///
+ public string PropertyName
+ {
+ get { return (Property != null) ? Property.Name : null; }
+ }
+
+ ///
+ /// Gets the property type.
+ ///
+ public Type PropertyType
+ {
+ get { return (Property != null) ? Property.PropertyType : null; }
+ }
+
+ ///
+ /// Gets the property.
+ ///
+ /// The property.
+ public PropertyInfo Property { get; private set; }
+
+ ///
+ /// Returns true if the property is dynamic.
+ ///
+ public bool IsDynamicProperty { get; private set; }
+
+ ///
+ /// Gets additional state.
+ ///
+ public IDictionary State
+ {
+ get
+ {
+ if (state == null)
+ {
+ state = new Dictionary();
+ }
+ return state;
+ }
+ }
+
+ ///
+ /// Determines if property should be fetched.
+ ///
+ public bool Fetch { get; set; }
+
+ ///
+ /// Determines if notifications should occur.
+ ///
+ public bool SuppressNotifications { get; set; }
+
+ ///
+ /// Gets the property behaviors.
+ ///
+ public object[] Behaviors { get; private set; }
+
+ ///
+ /// Gets the type converter.
+ ///
+ /// The type converter.
+ public TypeConverter TypeConverter { get; private set; }
+
+ ///
+ /// Gets the key builders.
+ ///
+ /// The key builders.
+ public ICollection KeyBuilders
+ {
+ get { return keyBuilders ?? NoKeysBuilders; }
+ }
+
+ ///
+ /// Gets the setter.
+ ///
+ /// The setter.
+ public ICollection Setters
+ {
+ get { return setters ?? NoSetters; }
+ }
+
+ ///
+ /// Gets the getter.
+ ///
+ /// The getter.
+ public ICollection Getters
+ {
+ get { return getters ?? NoHGetters; }
+ }
+
+ #region IDictionaryKeyBuilder Members
+
+ ///
+ /// Gets the key.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The descriptor.
+ ///
+ public string GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor descriptor)
+ {
+ if (keyBuilders != null)
+ {
+ foreach (var builder in keyBuilders)
+ {
+ key = builder.GetKey(dictionaryAdapter, key, this);
+ }
+ }
+
+ return key;
+ }
+
+ ///
+ /// Adds the key builder.
+ ///
+ /// The builder.
+ public PropertyDescriptor AddKeyBuilder(params IDictionaryKeyBuilder[] builders)
+ {
+ return AddKeyBuilders((IEnumerable)builders);
+ }
+
+ ///
+ /// Adds the key builders.
+ ///
+ /// The builders.
+ public PropertyDescriptor AddKeyBuilders(IEnumerable builders)
+ {
+ if (builders != null)
+ {
+ if (keyBuilders == null)
+ {
+ keyBuilders = new List(builders);
+ }
+ else
+ {
+ keyBuilders.AddRange(builders);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the key builders to the other
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopyKeyBuilders(PropertyDescriptor other)
+ {
+ if (keyBuilders != null)
+ {
+ other.AddKeyBuilders(keyBuilders);
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the selected key builders to the other
+ ///
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopyKeyBuilders(PropertyDescriptor other, Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ if (keyBuilders != null)
+ {
+ other.AddKeyBuilders(keyBuilders.Where(selector));
+ }
+ return this;
+ }
+
+ #endregion
+
+ #region IDictionaryPropertyGetter Members
+
+ ///
+ /// Gets the property value.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The stored value.
+ /// The descriptor.
+ /// true if return only existing.
+ ///
+ public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, object storedValue, PropertyDescriptor descriptor, bool ifExists)
+ {
+ key = GetKey(dictionaryAdapter, key, descriptor);
+ storedValue = storedValue ?? dictionaryAdapter.ReadProperty(key);
+
+ if (getters != null)
+ {
+ foreach (var getter in getters)
+ {
+ storedValue = getter.GetPropertyValue(dictionaryAdapter, key, storedValue, this, ifExists);
+ }
+ }
+
+ return storedValue;
+ }
+
+ ///
+ /// Adds the dictionary getter.
+ ///
+ /// The getter.
+ public PropertyDescriptor AddGetter(params IDictionaryPropertyGetter[] getters)
+ {
+ return AddGetters((IEnumerable)getters);
+ }
+
+ ///
+ /// Adds the dictionary getters.
+ ///
+ /// The getters.
+ public PropertyDescriptor AddGetters(IEnumerable gets)
+ {
+ if (gets != null)
+ {
+ if (getters == null)
+ {
+ getters = new List(gets);
+ }
+ else
+ {
+ getters.AddRange(gets);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the property getters to the other
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopyGetters(PropertyDescriptor other)
+ {
+ if (getters != null)
+ {
+ other.AddGetters(getters);
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the selected property getters to the other
+ ///
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopyGetters(PropertyDescriptor other, Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ if (getters != null)
+ {
+ other.AddGetters(getters.Where(selector));
+ }
+ return this;
+ }
+
+ #endregion
+
+ #region IDictionaryPropertySetter Members
+
+ ///
+ /// Sets the property value.
+ ///
+ /// The dictionary adapter.
+ /// The key.
+ /// The value.
+ /// The descriptor.
+ ///
+ public bool SetPropertyValue(IDictionaryAdapter dictionaryAdapter,
+ string key, ref object value, PropertyDescriptor descriptor)
+ {
+ bool consumed = false;
+
+ key = GetKey(dictionaryAdapter, key, descriptor);
+
+ if (setters != null)
+ {
+ foreach(var setter in setters)
+ {
+ if (!setter.SetPropertyValue(dictionaryAdapter, key, ref value, this))
+ {
+ consumed = true;
+ }
+ }
+ }
+
+ if (!consumed)
+ {
+ dictionaryAdapter.StoreProperty(this, key, value);
+ }
+
+ return !consumed;
+ }
+
+ ///
+ /// Adds the dictionary setter.
+ ///
+ /// The setter.
+ public PropertyDescriptor AddSetter(params IDictionaryPropertySetter[] setters)
+ {
+ return AddSetters((IEnumerable)setters);
+ }
+
+ ///
+ /// Adds the dictionary setters.
+ ///
+ /// The setters.
+ public PropertyDescriptor AddSetters(IEnumerable sets)
+ {
+ if (sets != null)
+ {
+ if (setters == null)
+ {
+ setters = new List(sets);
+ }
+ else
+ {
+ setters.AddRange(sets);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the property setters to the other
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopySetters(PropertyDescriptor other)
+ {
+ if (setters != null)
+ {
+ other.AddSetters(setters);
+ }
+ return this;
+ }
+
+ ///
+ /// Copies the selected property setters to the other
+ ///
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopySetters(PropertyDescriptor other, Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ if (setters != null)
+ {
+ other.AddSetters(setters.Where(selector));
+ }
+ return this;
+ }
+
+ #endregion
+
+ ///
+ /// Adds the behaviors.
+ ///
+ ///
+ ///
+ public PropertyDescriptor AddBehavior(params IDictionaryBehavior[] behaviors)
+ {
+ return AddBehaviors((IEnumerable)behaviors);
+ }
+
+ ///
+ /// Adds the behaviors.
+ ///
+ ///
+ ///
+ public PropertyDescriptor AddBehaviors(IEnumerable behaviors)
+ {
+ if (behaviors != null)
+ {
+ foreach (var behavior in behaviors)
+ {
+ InternalAddBehavior(behavior);
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// Adds the behaviors from the builders.
+ ///
+ ///
+ ///
+ public PropertyDescriptor AddBehaviors(params IDictionaryBehaviorBuilder[] builders)
+ {
+ AddBehaviors(builders.SelectMany(builder => builder.BuildBehaviors()));
+ return this;
+ }
+
+ ///
+ /// Copies the behaviors to the other
+ ///
+ ///
+ ///
+ public virtual PropertyDescriptor CopyBehaviors(PropertyDescriptor other)
+ {
+ return CopyKeyBuilders(other).CopyGetters(other).CopySetters(other);
+ }
+
+ ///
+ /// Copies the behaviors to the other
+ ///
+ ///
+ ///
+ ///
+ public PropertyDescriptor CopyBehaviors(PropertyDescriptor other, Func selector)
+ {
+ if (selector == null)
+ {
+ throw new ArgumentNullException("selector");
+ }
+ return CopyKeyBuilders(other, key => selector(key))
+ .CopyGetters(other, getter => selector(getter))
+ .CopySetters(other, setter => selector(setter));
+ }
+
+ protected virtual void InternalAddBehavior(IDictionaryBehavior behavior)
+ {
+ if (behavior is IDictionaryKeyBuilder)
+ {
+ AddKeyBuilder((IDictionaryKeyBuilder)behavior);
+ }
+
+ if (behavior is IDictionaryPropertyGetter)
+ {
+ AddGetter((IDictionaryPropertyGetter)behavior);
+ }
+
+ if (behavior is IDictionaryPropertySetter)
+ {
+ AddSetter((IDictionaryPropertySetter)behavior);
+ }
+ }
+
+ private void ObtainTypeConverter()
+ {
+ var converterType = AttributesUtil.GetTypeConverter(Property);
+
+ if (converterType != null)
+ {
+ TypeConverter = (TypeConverter) Activator.CreateInstance(converterType);
+ }
+ else
+ {
+ TypeConverter = TypeDescriptor.GetConverter(PropertyType);
+ }
+ }
+ }
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BehaviorVisitor.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BehaviorVisitor.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BehaviorVisitor.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BehaviorVisitor.cs Sun Feb 13 19:32:52 2011
@@ -0,0 +1,78 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+
+ internal class BehaviorVisitor
+ {
+ private List, Func>> conditions;
+
+ public BehaviorVisitor()
+ {
+ conditions = new List, Func>>();
+ }
+
+ public BehaviorVisitor OfType(Func apply)
+ {
+ return AddCondition(b => b is T, b => apply((T)b));
+ }
+
+ public BehaviorVisitor OfType(Action apply)
+ {
+ return AddCondition(b => b is T, b => { apply((T)b); return true; });
+ }
+
+ public BehaviorVisitor Match(Func match, Func apply)
+ {
+ return AddCondition(b => b is T && match((T)b), b => apply((T)b));
+ }
+
+ public BehaviorVisitor Match(Func match, Action apply)
+ {
+ return AddCondition(b => b is T && match((T)b), b => { apply((T)b); return true; });
+ }
+
+ public BehaviorVisitor Match(Func match, Func apply)
+ {
+ return Match(match, apply);
+ }
+
+ public BehaviorVisitor Match(Func match, Action apply)
+ {
+ return Match(match, apply);
+ }
+
+ public void Apply(IEnumerable behaviors)
+ {
+ foreach (var behavior in behaviors)
+ foreach (var condition in conditions)
+ {
+ if (condition.Key(behavior))
+ {
+ condition.Value(behavior);
+ }
+ }
+ }
+
+ private BehaviorVisitor AddCondition(Func predicate, Func action)
+ {
+ conditions.Add(new KeyValuePair, Func>(predicate, action));
+ return this;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BindingListInitializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BindingListInitializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BindingListInitializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\BindingListInitializer.cs Sun Feb 13 19:32:41 2011
@@ -0,0 +1,77 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.ComponentModel;
+
+ internal class BindingListInitializer : IValueInitializer
+ {
+ private readonly Action addAt;
+ private readonly Func addNew;
+ private readonly Action setAt;
+ private readonly Action removeAt;
+ private bool addingNew;
+
+ public BindingListInitializer(Action addAt, Func addNew,
+ Action setAt, Action removeAt)
+ {
+ this.addAt = addAt;
+ this.addNew = addNew;
+ this.setAt = setAt;
+ this.removeAt = removeAt;
+ }
+
+ public void Initialize(IDictionaryAdapter dictionaryAdapter, object value)
+ {
+ var bindingList = (BindingList)value;
+ if (addNew != null)
+ {
+ bindingList.AddingNew += (sender, args) =>
+ {
+ args.NewObject = addNew();
+ addingNew = true;
+ };
+ }
+ bindingList.ListChanged += (sender, args) =>
+ {
+ switch (args.ListChangedType)
+ {
+ case ListChangedType.ItemAdded:
+ if (addingNew == false && addAt != null)
+ {
+ addAt(args.NewIndex, bindingList[args.NewIndex]);
+ }
+ addingNew = false;
+ break;
+ case ListChangedType.ItemChanged:
+ if (setAt != null)
+ {
+ setAt(args.NewIndex, bindingList[args.NewIndex]);
+ }
+ break;
+ case ListChangedType.ItemDeleted:
+ if (removeAt != null)
+ {
+ removeAt(args.NewIndex);
+ }
+ break;
+ }
+ };
+ }
+ }
+#endif
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValue.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValue.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValue.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValue.cs Sun Feb 13 19:32:34 2011
@@ -0,0 +1,36 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ internal abstract class DynamicValue : IDynamicValue
+ {
+ object IDynamicValue.GetValue()
+ {
+ return Value;
+ }
+
+ public abstract T Value { get; }
+
+ public override string ToString()
+ {
+ var value = Value;
+ if (value != null)
+ {
+ return value.ToString();
+ }
+ return base.ToString();
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValueDelegate.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValueDelegate.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValueDelegate.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\DynamicValueDelegate.cs Sun Feb 13 19:32:22 2011
@@ -0,0 +1,33 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+
+ internal class DynamicValueDelegate : DynamicValue
+ {
+ private readonly Func dynamicDelegate;
+
+ public DynamicValueDelegate(Func dynamicDelegate)
+ {
+ this.dynamicDelegate = dynamicDelegate;
+ }
+
+ public override T Value
+ {
+ get { return dynamicDelegate(); }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableBindingList.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableBindingList.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableBindingList.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableBindingList.cs Sun Feb 13 19:32:12 2011
@@ -0,0 +1,96 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System.Collections.Generic;
+ using System.ComponentModel;
+
+ internal class EditableBindingList : BindingList, IList, IEditableObject, IRevertibleChangeTracking
+ {
+ private bool isEditing;
+ private List snapshot;
+
+ public EditableBindingList()
+ {
+ }
+
+ public EditableBindingList(IList initial)
+ : base(initial)
+ {
+ }
+
+ public bool IsChanged
+ {
+ get
+ {
+ if (snapshot == null || snapshot.Count != Count)
+ return false;
+
+ var items = GetEnumerator();
+ var snapshotItems = snapshot.GetEnumerator();
+
+ while (items.MoveNext() && snapshotItems.MoveNext())
+ {
+ if (ReferenceEquals(items.Current, snapshotItems.Current) == false)
+ return false;
+
+ var tracked = items.Current as IChangeTracking;
+ if (tracked != null && tracked.IsChanged)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public void BeginEdit()
+ {
+ if (!isEditing)
+ {
+ snapshot = new List(this);
+ isEditing = true;
+ }
+ }
+
+ public void EndEdit()
+ {
+ isEditing = false;
+ snapshot = null;
+ }
+
+ public void CancelEdit()
+ {
+ if (isEditing)
+ {
+ Clear();
+ foreach (var item in snapshot) Add(item);
+ snapshot = null;
+ isEditing = false;
+ }
+ }
+
+ public void AcceptChanges()
+ {
+ BeginEdit();
+ }
+
+ public void RejectChanges()
+ {
+ CancelEdit();
+ }
+ }
+#endif
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableList.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableList.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableList.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\EditableList.cs Sun Feb 13 19:35:14 2011
@@ -0,0 +1,91 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+
+ internal class EditableList : List, IEditableObject, IRevertibleChangeTracking
+ {
+ private bool isEditing;
+ private List snapshot;
+
+ public void BeginEdit()
+ {
+ if (!isEditing)
+ {
+ snapshot = new List(this);
+ isEditing = true;
+ }
+ }
+
+ public bool IsChanged
+ {
+ get
+ {
+ if (snapshot == null || snapshot.Count != Count)
+ return false;
+
+ var items = GetEnumerator();
+ var snapshotItems = snapshot.GetEnumerator();
+
+ while (items.MoveNext() && snapshotItems.MoveNext())
+ {
+ if (ReferenceEquals(items.Current, snapshotItems.Current) == false)
+ return false;
+
+ var tracked = items.Current as IChangeTracking;
+ if (tracked != null && tracked.IsChanged)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public void EndEdit()
+ {
+ isEditing = false;
+ snapshot = null;
+ }
+
+ public void CancelEdit()
+ {
+ if (isEditing)
+ {
+ Clear();
+ AddRange(snapshot);
+ snapshot = null;
+ isEditing = false;
+ }
+ }
+
+ public void AcceptChanges()
+ {
+ BeginEdit();
+ }
+
+ public void RejectChanges()
+ {
+ CancelEdit();
+ }
+ }
+
+ internal class EditableList : EditableList, IList
+ {
+
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IDynamicValue.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IDynamicValue.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IDynamicValue.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IDynamicValue.cs Sun Feb 13 19:32:01 2011
@@ -0,0 +1,33 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ ///
+ /// Contract for dynamic value resolution.
+ ///
+ internal interface IDynamicValue
+ {
+ object GetValue();
+ }
+
+ ///
+ /// Contract for typed dynamic value resolution.
+ ///
+ ///
+ internal interface IDynamicValue : IDynamicValue
+ {
+ T Value { get; }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IValueInitializer.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IValueInitializer.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IValueInitializer.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\IValueInitializer.cs Sun Feb 13 19:31:53 2011
@@ -0,0 +1,7 @@
+namespace Castle.Components.DictionaryAdapter
+{
+ internal interface IValueInitializer
+ {
+ void Initialize(IDictionaryAdapter dictionaryAdapter, object value);
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\PriorityBehavior.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\PriorityBehavior.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\Util\PriorityBehavior.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\Util\PriorityBehavior.cs Sun Feb 13 18:56:54 2011
@@ -0,0 +1,59 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ static class PriorityBehaviorExtensions
+ {
+ class PriorityBehavior : IComparable> where T : IDictionaryBehavior
+ {
+ public PriorityBehavior(T behavior, int priority)
+ {
+ Behavior = behavior;
+ Priority = priority;
+ }
+
+ public T Behavior { get; private set; }
+
+ public int Priority { get; private set; }
+
+ public int CompareTo(PriorityBehavior other)
+ {
+ var order = Behavior.ExecutionOrder - other.Behavior.ExecutionOrder;
+ return (order == 0) ? Priority - other.Priority : order;
+ }
+ }
+
+ public static IEnumerable Prioritize(this IEnumerable first, params IEnumerable[] remaining)
+ where T : IDictionaryBehavior
+ {
+ var allBehaviors = new[] { first }.Union(remaining).Where(behaviors => behaviors != null && behaviors.Any()).ToArray();
+
+ switch (allBehaviors.Length)
+ {
+ case 0:
+ return Enumerable.Empty();
+ case 1:
+ return allBehaviors[0].OrderBy(behavior => behavior.ExecutionOrder);
+ default:
+ return allBehaviors.SelectMany((bs, priority) => bs.Select(b => new PriorityBehavior(b, priority)))
+ .OrderBy(priority => priority).Select(priority => priority.Behavior);;
+ }
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathAdapter.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathAdapter.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathAdapter.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathAdapter.cs Sun Feb 13 19:31:16 2011
@@ -0,0 +1,693 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.f
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Linq;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using System.Xml.XPath;
+
+ internal class XPathAdapter : DictionaryBehaviorAttribute, IDictionaryInitializer,
+ IDictionaryPropertyGetter, IDictionaryPropertySetter,
+ IDictionaryCreateStrategy
+ {
+ private readonly Func createRoot;
+ private XPathNavigator root;
+ private XmlMetadata xmlMeta;
+
+ public XPathNavigator Root
+ {
+ get { return EnsureOffRoot(); }
+ }
+
+ public XPathAdapter Parent { get; private set; }
+
+ public IXPathNavigable Source { get; private set; }
+
+ public XPathContext Context { get; private set; }
+
+ #region Init
+
+ public XPathAdapter() : this(new XmlDocument())
+ {
+ }
+
+ public XPathAdapter(IXPathNavigable source)
+ {
+ Source = source;
+ Context = new XPathContext();
+ root = source.CreateNavigator();
+ }
+
+ protected XPathAdapter(XPathNavigator source, XPathAdapter parent)
+ {
+ Parent = parent;
+ Context = parent.Context.CreateChild();
+ root = source.Clone();
+ }
+
+ protected XPathAdapter(Func createSource, XPathAdapter parent)
+ {
+ Parent = parent;
+ Context = parent.Context.CreateChild();
+ createRoot = createSource;
+ }
+
+ void IDictionaryInitializer.Initialize(IDictionaryAdapter dictionaryAdapter, object[] behaviors)
+ {
+ var meta = dictionaryAdapter.Meta;
+ if (meta.MetaInitializers.OfType().FirstOrDefault() == null)
+ {
+ throw new InvalidOperationException(string.Format(
+ "Interface {0} requested xpath support, but was not configured properly. " +
+ "Did you forget to add an XPathBehavior?", meta.Type.FullName));
+ }
+
+ dictionaryAdapter.This.CreateStrategy = this;
+
+ Context.ApplyBehaviors(behaviors);
+ xmlMeta = dictionaryAdapter.GetXmlMeta();
+
+ if (string.IsNullOrEmpty(xmlMeta.XmlType.Namespace) == false)
+ {
+ Context.AddNamespace(string.Empty, xmlMeta.XmlType.Namespace);
+ }
+
+ if (Parent == null)
+ {
+ foreach (var behavior in behaviors)
+ {
+ if (behavior is XPathAttribute)
+ {
+ var attrib = (XPathAttribute)behavior;
+ var compiledExpression = attrib.CompiledExpression;
+ if (MoveOffRoot(root, XPathNodeType.Element) == false || Context.Matches(compiledExpression, root))
+ {
+ break;
+ }
+
+ var navigator = Context.SelectSingleNode(compiledExpression, root);
+ if (navigator != null)
+ {
+ root = navigator;
+ break;
+ }
+ }
+ }
+ MoveOffRoot(root, XPathNodeType.Element);
+ }
+ }
+
+ #endregion
+
+ #region Behaviors
+
+ object IDictionaryPropertyGetter.GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key,
+ object storedValue, PropertyDescriptor property, bool ifExists)
+ {
+ if (ShouldIgnoreProperty(property))
+ {
+ return storedValue;
+ }
+
+ var cached = dictionaryAdapter.This.ExtendedProperties[property.PropertyName];
+ if (cached != null) return cached;
+
+ var result = EvaluateProperty(key, property, dictionaryAdapter);
+ return ReadProperty(result, ifExists, dictionaryAdapter);
+ }
+
+ bool IDictionaryPropertySetter.SetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key,
+ ref object value, PropertyDescriptor property)
+ {
+ if (ShouldIgnoreProperty(property))
+ {
+ return true;
+ }
+
+ EnsureOffRoot();
+
+ if (root.CanEdit)
+ {
+ var result = EvaluateProperty(key, property, dictionaryAdapter);
+ if (result.CanWrite)
+ {
+ WriteProperty(result, value, dictionaryAdapter);
+ }
+ }
+
+ return false;
+ }
+
+ object IDictionaryCreateStrategy.Create(IDictionaryAdapter adapter, Type type, IDictionary dictionary)
+ {
+ dictionary = dictionary ?? new Hashtable();
+ var descriptor = new DictionaryDescriptor();
+ adapter.This.Descriptor.CopyBehaviors(descriptor, b => b is XPathAdapter == false);
+ descriptor.AddBehavior(XPathBehavior.Instance).AddBehavior(new XPathAdapter(new XmlDocument()));
+ return adapter.This.Factory.GetAdapter(type, dictionary, descriptor);
+ }
+
+ #endregion
+
+ #region Reading
+
+ private object ReadProperty(XPathResult result, bool ifExists, IDictionaryAdapter dictionaryAdapter)
+ {
+ object value;
+ var propertyType = result.Type;
+
+ if (ReadCustom(result, out value))
+ return value;
+
+ if (propertyType != typeof(string))
+ {
+ if (typeof(IXPathNavigable).IsAssignableFrom(propertyType))
+ return ReadFragment(result);
+
+ if (propertyType.IsArray || typeof(IEnumerable).IsAssignableFrom(propertyType))
+ return ReadCollection(result, dictionaryAdapter);
+
+ if (propertyType.IsInterface)
+ return ReadComponent(result, ifExists, dictionaryAdapter);
+ }
+
+ return ReadSimple(result);
+ }
+
+ private object ReadFragment(XPathResult result)
+ {
+ var node = result.GetNavigator(false);
+ if (result.Type == typeof(XmlElement))
+ {
+ var document = new XmlDocument();
+ document.Load(node.ReadSubtree());
+ return document.DocumentElement;
+ }
+ return node.Clone();
+ }
+
+ private object ReadSimple(XPathResult result)
+ {
+ var node = result.GetNavigator(false);
+ if (node != null)
+ {
+ if (result.Type.IsEnum)
+ return Enum.Parse(result.Type, node.Value);
+
+ try
+ {
+ return node.ValueAs(result.Type);
+ }
+ catch (InvalidCastException)
+ {
+ object value;
+ if (DefaultXmlSerializer.Instance.ReadObject(result, node, out value))
+ return value;
+ }
+ }
+ if (result.Result != null)
+ return Convert.ChangeType(result.Result, result.Type);
+
+ return null;
+ }
+
+ private object ReadComponent(XPathResult result, bool ifExists, IDictionaryAdapter dictionaryAdapter)
+ {
+ XPathAdapter adapter;
+ var source = result.GetNavigator(false);
+ if (source == null && ifExists) return null;
+
+ var elementType = result.Type;
+ if (source != null)
+ {
+ if (result.XmlMeta != null)
+ {
+ elementType = result.XmlMeta.Type;
+ }
+ else
+ {
+ var xmlType = Context.GetXmlType(source);
+ elementType = dictionaryAdapter.GetXmlSubclass(xmlType, elementType) ?? elementType;
+ }
+ adapter = new XPathAdapter(source, this);
+ }
+ else
+ {
+ Func createSource = () => result.GetNavigator(true);
+ adapter = new XPathAdapter(createSource, this);
+ }
+
+ var component = dictionaryAdapter.This.Factory.GetAdapter(elementType, new Hashtable(),
+ new DictionaryDescriptor().AddBehavior(XPathBehavior.Instance, adapter));
+
+ if (result.Property != null)
+ dictionaryAdapter.This.ExtendedProperties[result.Property.PropertyName] = component;
+
+ return component;
+ }
+
+ private object ReadCollection(XPathResult result, IDictionaryAdapter dictionaryAdapter)
+ {
+ if (result.Type.IsArray)
+ return ReadArray(result, dictionaryAdapter);
+
+ if (result.Type.IsGenericType)
+ return ReadList(result, dictionaryAdapter);
+
+ return null;
+ }
+
+ private object ReadArray(XPathResult result, IDictionaryAdapter dictionaryAdapter)
+ {
+ var itemType = result.Type.GetElementType();
+ var items = result.GetNodes(itemType, type => dictionaryAdapter.GetXmlMeta(type))
+ .Select(node => ReadProperty(node, false, dictionaryAdapter)).ToArray();
+ var array = Array.CreateInstance(itemType, items.Length);
+ items.CopyTo(array, 0);
+ return array;
+ }
+
+ private object ReadList(XPathResult result, IDictionaryAdapter dictionaryAdapter)
+ {
+ Type listType = null, initializerType = null;
+ var arguments = result.Type.GetGenericArguments();
+ var genericDef = result.Type.GetGenericTypeDefinition();
+ var itemType = arguments[0];
+
+ if (genericDef == typeof(List<>))
+ {
+ listType = typeof(EditableList<>).MakeGenericType(arguments);
+ }
+ else
+ {
+ listType = typeof(EditableBindingList<>).MakeGenericType(arguments);
+ initializerType = typeof(BindingListInitializer<>).MakeGenericType(arguments);
+ }
+
+ var list = (IList)Activator.CreateInstance(listType);
+ Func getXmlMeta = type => dictionaryAdapter.GetXmlMeta(type);
+
+ foreach (var item in result.GetNodes(itemType, getXmlMeta))
+ {
+ list.Add(ReadProperty(item, false, dictionaryAdapter));
+ }
+
+ if (initializerType != null)
+ {
+ Func addNew = () =>
+ {
+ var node = result.CreateNode(itemType, null, getXmlMeta);
+ return ReadProperty(node, false, dictionaryAdapter);
+ };
+
+ Action addAt = (index, item) =>
+ {
+ var node = result.CreateNode(itemType, item, getXmlMeta);
+ WriteProperty(node, item, dictionaryAdapter);
+ };
+
+ Action setAt = (index, item) =>
+ {
+ var node = result.GetNodeAt(itemType, index);
+ WriteProperty(node, item, dictionaryAdapter);
+ };
+
+ Action removeAt = index => result.RemoveAt(index);
+
+ var initializer = (IValueInitializer)Activator.CreateInstance(
+ initializerType, addAt, addNew, setAt, removeAt);
+ initializer.Initialize(dictionaryAdapter, list);
+ }
+
+ return list;
+ }
+
+ private bool ReadCustom(XPathResult result, out object value)
+ {
+ return result.ReadObject(out value);
+ }
+
+ #endregion
+
+ #region Writing
+
+ private void WriteProperty(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ var propertyType = result.Type;
+
+ if (WriteCustom(result, value, dictionaryAdapter))
+ return;
+
+ if (propertyType == typeof(string))
+ {
+ WriteSimple(result, value, dictionaryAdapter);
+ }
+ else if (typeof(IXPathNavigable).IsAssignableFrom(propertyType))
+ {
+ WriteFragment(result, (IXPathNavigable)value);
+ }
+ else if (propertyType.IsArray || typeof(IEnumerable).IsAssignableFrom(propertyType))
+ {
+ WriteCollection(result, value, dictionaryAdapter);
+ }
+ else if (propertyType.IsInterface)
+ {
+ WriteComponent(result, value, dictionaryAdapter);
+ }
+ else
+ {
+ WriteSimple(result, value, dictionaryAdapter);
+ }
+ }
+
+ private void WriteFragment(XPathResult result, IXPathNavigable value)
+ {
+ var node = result.GetNavigator(true);
+ if (node == null)
+ {
+ root.AppendChild(value.CreateNavigator());
+ }
+ else if (value != null)
+ {
+ node.ReplaceSelf(value.CreateNavigator());
+ }
+ else
+ {
+ node.DeleteSelf();
+ }
+ }
+
+ private void WriteSimple(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ if (value == null)
+ {
+ result.Remove();
+ if (result.Property != null)
+ dictionaryAdapter.This.ExtendedProperties.Remove(result.Property.PropertyName);
+ return;
+ }
+
+ var node = result.GetNavigator(true);
+
+ if (result.Type.IsEnum)
+ {
+ node.SetTypedValue(value.ToString());
+ }
+ else
+ {
+ try
+ {
+ node.SetTypedValue(value);
+ }
+ catch (InvalidCastException)
+ {
+ if (DefaultXmlSerializer.Instance.WriteObject(result, node, value) && result.Property != null)
+ {
+ dictionaryAdapter.This.ExtendedProperties[result.Property.PropertyName] = value;
+ }
+ }
+ }
+ }
+
+ private void WriteComponent(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ if (result.Property != null)
+ {
+ dictionaryAdapter.This.ExtendedProperties.Remove(result.Property.PropertyName);
+ }
+
+ if (value == null)
+ {
+ result.Remove();
+ return;
+ }
+
+ var source = value as IDictionaryAdapter;
+ if (source != null)
+ {
+ var node = result.RemoveChildren();
+ if (result.Type != source.Meta.Type && result.OmitPolymorphism == false)
+ {
+ var xmlType = source.GetXmlMeta().XmlType;
+ Context.SetXmlType(xmlType.TypeName, xmlType.Namespace, node);
+ }
+ var element = (IDictionaryAdapter)ReadComponent(result, false, dictionaryAdapter);
+ source.CopyTo(element);
+ }
+ }
+
+ private void WriteCollection(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ result.Remove();
+
+ if (value != null)
+ {
+ if (result.Type.IsArray)
+ {
+ WriteArray(result, value, dictionaryAdapter);
+ }
+ else if (result.Type.IsGenericType)
+ {
+ WriteList(result, value, dictionaryAdapter);
+ }
+ }
+ }
+
+ private void WriteArray(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ var array = (Array)value;
+ var itemType = array.GetType().GetElementType();
+
+ foreach (var item in array)
+ {
+ var node = result.CreateNode(itemType, item, type => dictionaryAdapter.GetXmlMeta(type));
+ WriteProperty(node, item, dictionaryAdapter);
+ }
+ }
+
+ private void WriteList(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ var arguments = result.Type.GetGenericArguments();
+ var itemType = arguments[0];
+
+ foreach (var item in (IEnumerable)value)
+ {
+ var node = result.CreateNode(itemType, item, type => dictionaryAdapter.GetXmlMeta(type));
+ WriteProperty(node, item, dictionaryAdapter);
+ }
+ }
+
+ private bool WriteCustom(XPathResult result, object value, IDictionaryAdapter dictionaryAdapter)
+ {
+ if (result.WriteObject(value))
+ {
+ if (result.Property != null)
+ {
+ dictionaryAdapter.This.ExtendedProperties[result.Property.PropertyName] = value;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
+
+ #region Helpers
+
+ public static XPathAdapter For(object adapter)
+ {
+ if (adapter == null)
+ {
+ throw new ArgumentNullException("adapter");
+ }
+
+ var dictionaryAdapter = adapter as IDictionaryAdapter;
+
+ if (dictionaryAdapter != null)
+ {
+ XPathAdapter xpathAdapter = null;
+ var getters = dictionaryAdapter.This.Descriptor.Getters;
+ if (getters != null)
+ xpathAdapter = getters.OfType().SingleOrDefault();
+ if (xpathAdapter != null) return xpathAdapter;
+ }
+
+ return null;
+ }
+
+ private XPathResult EvaluateProperty(string key, PropertyDescriptor property, IDictionaryAdapter dictionaryAdapter)
+ {
+ object result;
+ XPathExpression xpath = null;
+ object matchingBehavior = null;
+ Func create = null;
+
+ object xmlType = dictionaryAdapter.GetXmlMeta(property.Property.DeclaringType).XmlType;
+ var keyContext = Context.CreateChild(Enumerable.Repeat(xmlType, 1).Union(property.Behaviors));
+
+ foreach (var behavior in property.Behaviors)
+ {
+ string name = key, ns = null;
+ Func matchingCreate = null;
+
+ if (behavior is XmlElementAttribute)
+ {
+ xpath = XPathElement;
+ var node = root.Clone();
+ var attrib = (XmlElementAttribute)behavior;
+ if (string.IsNullOrEmpty(attrib.ElementName) == false)
+ {
+ name = attrib.ElementName;
+ }
+ if (string.IsNullOrEmpty(attrib.Namespace) == false)
+ {
+ ns = attrib.Namespace;
+ }
+ matchingCreate = () => keyContext.AppendElement(name, ns, node);
+ }
+ else if (behavior is XmlAttributeAttribute)
+ {
+ xpath = XPathAttribute;
+ var node = root.Clone();
+ var attrib = (XmlAttributeAttribute)behavior;
+ if (string.IsNullOrEmpty(attrib.AttributeName) == false)
+ {
+ name = attrib.AttributeName;
+ }
+ if (string.IsNullOrEmpty(attrib.Namespace) == false)
+ {
+ ns = attrib.Namespace;
+ }
+ matchingCreate = () => keyContext.CreateAttribute(name, ns, node);
+ }
+ else if (behavior is XmlArrayAttribute)
+ {
+ xpath = XPathElement;
+ var node = root.Clone();
+ var attrib = (XmlArrayAttribute)behavior;
+ if (string.IsNullOrEmpty(attrib.ElementName) == false)
+ {
+ name = attrib.ElementName;
+ }
+ if (string.IsNullOrEmpty(attrib.Namespace) == false)
+ {
+ ns = attrib.Namespace;
+ }
+ matchingCreate = () => keyContext.AppendElement(name, ns, node);
+ }
+ else if (behavior is XPathAttribute)
+ {
+ var attrib = (XPathAttribute)behavior;
+ xpath = attrib.CompiledExpression;
+ }
+ else
+ {
+ continue;
+ }
+
+ if (xpath != null)
+ {
+ keyContext.Arguments.Clear();
+ keyContext.Arguments.AddParam("key", "", name);
+ keyContext.Arguments.AddParam("ns", "", ns ?? XPathContext.IgnoreNamespace);
+ if (keyContext.Evaluate(xpath, Root, out result))
+ {
+ create = matchingCreate ?? create;
+ return new XPathResult(property, result, keyContext, behavior, create);
+ }
+ }
+
+ matchingBehavior = matchingBehavior ?? behavior;
+ create = create ?? matchingCreate;
+ }
+
+ if (xpath != null)
+ {
+ return new XPathResult(property, null, keyContext, matchingBehavior, create);
+ }
+
+ keyContext.Arguments.Clear();
+ keyContext.Arguments.AddParam("key", "", key);
+ keyContext.Arguments.AddParam("ns", "", XPathContext.IgnoreNamespace);
+ create = create ?? (() => keyContext.AppendElement(key, null, root));
+ keyContext.Evaluate(XPathElementOrAttribute, Root, out result);
+ return new XPathResult(property, result, keyContext, null, create);
+ }
+
+ private static bool ShouldIgnoreProperty(PropertyDescriptor property)
+ {
+ return property.Behaviors.Any(behavior => behavior is XmlIgnoreAttribute);
+ }
+
+ private XPathNavigator EnsureOffRoot()
+ {
+ if (root == null && createRoot != null)
+ {
+ root = createRoot().Clone();
+ }
+
+ if (root != null && MoveOffRoot(root, XPathNodeType.Element) == false)
+ {
+ string elementName;
+ string namespaceUri = "";
+ var xmlRoot = xmlMeta.XmlRoot;
+ if (xmlRoot != null)
+ {
+ elementName = xmlRoot.ElementName;
+ namespaceUri = xmlRoot.Namespace;
+ }
+ else
+ {
+ elementName = xmlMeta.XmlType.TypeName;
+ }
+ root = Context.AppendElement(elementName, namespaceUri, root);
+ Context.AddStandardNamespaces(root);
+ }
+
+ return root;
+ }
+
+ private static bool MoveOffRoot(XPathNavigator source, XPathNodeType to)
+ {
+ if (source.NodeType == XPathNodeType.Root)
+ {
+ return source.MoveToChild(to);
+ }
+ return true;
+ }
+
+ #endregion
+
+ #region XPath
+
+ private static readonly XPathExpression XPathElement =
+ XPathExpression.Compile("*[castle-da:match($key,$ns)]");
+
+ private static readonly XPathExpression XPathAttribute =
+ XPathExpression.Compile("@*[castle-da:match($key,$ns)]");
+
+ private static readonly XPathExpression XPathElementOrAttribute =
+ XPathExpression.Compile("(*|@*)[castle-da:match($key,$ns)]");
+
+ #endregion
+ }
+#endif
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathBehavior.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathBehavior.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathBehavior.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathBehavior.cs Sun Feb 13 20:02:15 2011
@@ -0,0 +1,100 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Xml;
+ using System.Xml.Serialization;
+
+ internal class XPathBehavior : DictionaryBehaviorAttribute, IDictionaryMetaInitializer
+ {
+ public static readonly XPathBehavior Instance = new XPathBehavior();
+
+ void IDictionaryMetaInitializer.Initialize(IDictionaryAdapterFactory factory, DictionaryAdapterMeta dictionaryMeta)
+ {
+ var type = dictionaryMeta.Type;
+ string defaultNamespace = null;
+ XmlTypeAttribute xmlType = null;
+ XmlRootAttribute xmlRoot = null;
+ List xmlIncludes = null;
+
+ new BehaviorVisitor()
+ .OfType(attrib =>
+ {
+ xmlType = attrib;
+ })
+ .OfType(attrib =>
+ {
+ xmlRoot = attrib;
+ })
+ .OfType(attrib =>
+ {
+ if (attrib.Default)
+ defaultNamespace = attrib.NamespaceUri;
+ })
+ .OfType(attrib =>
+ {
+ xmlIncludes = xmlIncludes ?? new List();
+ if (type != attrib.Type && type.IsAssignableFrom(attrib.Type))
+ {
+ xmlIncludes.Add(attrib.Type);
+ }
+ })
+ .Apply(dictionaryMeta.Behaviors);
+
+ if (xmlType == null)
+ {
+ xmlType = new XmlTypeAttribute
+ {
+ TypeName = type.Name,
+ Namespace = defaultNamespace
+ };
+ if (xmlType.TypeName.StartsWith("I"))
+ {
+ xmlType.TypeName = xmlType.TypeName.Substring(1);
+ }
+ }
+ else if (xmlType.Namespace == null)
+ xmlType.Namespace = defaultNamespace;
+
+ dictionaryMeta.SetXmlMeta(new XmlMetadata(type, xmlType, xmlRoot, xmlIncludes));
+ }
+ }
+
+ #region Class: XmlMetadata
+
+ internal class XmlMetadata
+ {
+ public XmlMetadata(Type type, XmlTypeAttribute xmlType, XmlRootAttribute xmlRoot, IEnumerable xmlIncludes)
+ {
+ Type = type;
+ XmlType = xmlType;
+ XmlRoot = xmlRoot;
+ XmlIncludes = xmlIncludes;
+ }
+
+ public Type Type { get; private set; }
+
+ public XmlTypeAttribute XmlType { get; private set; }
+
+ public XmlRootAttribute XmlRoot { get; private set; }
+
+ public IEnumerable XmlIncludes { get; private set; }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathContext.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathContext.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathContext.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathContext.cs Sun Feb 13 19:31:28 2011
@@ -0,0 +1,422 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using System.Xml.XPath;
+ using System.Xml.Xsl;
+
+ internal class XPathContext : XsltContext
+ {
+ private readonly XPathContext parent;
+ private IDictionary> functions;
+ private List serializers;
+ private int prefixCount;
+
+ public const string Prefix = "castle-da";
+ public const string NamespaceUri = "urn:castleproject.org:da";
+ public const string IgnoreNamespace = "_";
+ private const string Xsd = "http://www.w3.org/2001/XMLSchema";
+ private const string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
+
+ public XPathContext()
+ : this(new NameTable())
+ {
+ }
+
+ public XPathContext(NameTable nameTable)
+ : base(nameTable)
+ {
+ Arguments = new XsltArgumentList();
+ functions = new Dictionary>();
+ AddNamespace("xsi", Xsi);
+ AddNamespace("xsd", Xsd);
+ AddNamespace(Prefix, NamespaceUri);
+ AddFunction(Prefix, "match", MatchFunction.Instance);
+ }
+
+ public XPathContext(XPathContext parent)
+ : base((NameTable)parent.NameTable)
+ {
+ this.parent = parent;
+ Arguments = new XsltArgumentList();
+ functions = new Dictionary>();
+ }
+
+ public override string DefaultNamespace
+ {
+ get
+ {
+ var defaultNamespace = base.DefaultNamespace;
+ if (string.IsNullOrEmpty(defaultNamespace) && parent != null)
+ defaultNamespace = parent.DefaultNamespace;
+ return defaultNamespace;
+ }
+ }
+
+ public XsltArgumentList Arguments { get; private set; }
+
+ public IEnumerable ListItemMeta { get; private set; }
+
+ public IEnumerable Serializers
+ {
+ get
+ {
+ var mine = serializers ?? Enumerable.Empty();
+ var parents = (parent != null) ? parent.Serializers : Enumerable.Empty();
+ return mine.Union(parents);
+ }
+ }
+
+ public XPathContext ApplyBehaviors(IEnumerable behaviors)
+ {
+ new BehaviorVisitor()
+ .OfType(attrib =>
+ {
+ if (string.IsNullOrEmpty(attrib.Namespace) == false)
+ AddNamespace(string.Empty, attrib.Namespace);
+ })
+ .OfType(attrib =>
+ {
+ AddNamespace(attrib.Prefix, attrib.NamespaceUri);
+ if (attrib.Default)
+ AddNamespace(string.Empty, attrib.NamespaceUri);
+ })
+ .OfType(attrib =>
+ {
+ ListItemMeta = ListItemMeta ?? new List();
+ ((List)ListItemMeta).Add(attrib);
+ })
+ .OfType(attrib =>
+ {
+ AddFunction(attrib.Prefix, attrib.Name, attrib.Function);
+ })
+ .OfType(attrib =>
+ {
+ AddSerializer(attrib);
+ })
+ .Apply(behaviors);
+ return this;
+ }
+
+ public XPathContext CreateChild(IEnumerable behaviors)
+ {
+ return new XPathContext(this).ApplyBehaviors(behaviors);
+ }
+
+ public XPathContext CreateChild(params object[] behaviors)
+ {
+ return CreateChild((IEnumerable)behaviors);
+ }
+
+ public override bool HasNamespace(string prefix)
+ {
+ return base.HasNamespace(prefix) || (parent != null && parent.HasNamespace(prefix));
+ }
+
+ public override string LookupNamespace(string prefix)
+ {
+ var uri = base.LookupNamespace(prefix);
+ if (uri == null && parent != null)
+ uri = parent.LookupNamespace(prefix);
+ return uri;
+ }
+
+ public override string LookupPrefix(string uri)
+ {
+ var prefix = base.LookupPrefix(uri);
+ if (string.IsNullOrEmpty(prefix) && parent != null)
+ prefix = parent.LookupPrefix(uri);
+ return prefix;
+ }
+
+ public string AddNamespace(string namespaceUri)
+ {
+ var prefix = LookupPrefix(namespaceUri);
+ if (string.IsNullOrEmpty(prefix))
+ {
+ prefix = GetUniquePrefix();
+ AddNamespace(prefix, namespaceUri);
+ }
+ return prefix;
+ }
+
+ public XPathContext AddSerializer(IXPathSerializer serializer)
+ {
+ serializers = serializers ?? new List();
+ serializers.Insert(0, serializer);
+ return this;
+ }
+
+ public XPathContext AddFunction(string prefix, string name, IXsltContextFunction function)
+ {
+ functions[GetQualifiedName(prefix, name)] = () => function;
+ return this;
+ }
+
+ public XPathContext AddFunction(string prefix, string name, Func function)
+ {
+ functions[GetQualifiedName(prefix, name)] = function;
+ return this;
+ }
+
+ public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes)
+ {
+ Func function;
+ if (functions.TryGetValue(GetQualifiedName(prefix, name), out function))
+ return function();
+ return (parent != null) ? parent.ResolveFunction(prefix, name, argTypes) : null;
+ }
+
+ public override IXsltContextVariable ResolveVariable(string prefix, string name)
+ {
+ return new XPathVariable(name);
+ }
+
+ public bool Evaluate(XPathExpression xpath, XPathNavigator source, out object result)
+ {
+ xpath = (XPathExpression)xpath.Clone();
+ xpath.SetContext(this);
+ result = source.Evaluate(xpath);
+ if (xpath.ReturnType == XPathResultType.NodeSet)
+ {
+ if (((XPathNodeIterator)result).Count == 0)
+ result = null;
+ }
+ return result != null;
+ }
+
+ public XPathNavigator SelectSingleNode(XPathExpression xpath, XPathNavigator source)
+ {
+ xpath = (XPathExpression)xpath.Clone();
+ xpath.SetContext(this);
+ return source.SelectSingleNode(xpath);
+ }
+
+ public bool Matches(XPathExpression xpath, XPathNavigator source)
+ {
+ xpath = (XPathExpression)xpath.Clone();
+ xpath.SetContext(this);
+ return source.Matches(xpath);
+ }
+
+ public void AddStandardNamespaces(XPathNavigator source)
+ {
+ CreateNamespace("xsi", Xsi, source);
+ CreateNamespace("xsd", Xsd, source);
+ }
+
+ public string CreateNamespace(string prefix, string namespaceUri, XPathNavigator source)
+ {
+ if (string.IsNullOrEmpty(namespaceUri) == false)
+ {
+ source = source.Clone();
+ source.MoveToRoot();
+ source.MoveToChild(XPathNodeType.Element);
+
+ if (string.IsNullOrEmpty(prefix))
+ prefix = AddNamespace(namespaceUri);
+
+ var existing = source.GetNamespace(prefix);
+ if (existing == namespaceUri) return prefix;
+ if (string.IsNullOrEmpty(existing) == false) return null;
+
+ source.CreateAttribute("xmlns", prefix, "", namespaceUri);
+ }
+ return prefix;
+ }
+
+ public XPathNavigator CreateAttribute(string name, string namespaceUri, XPathNavigator source)
+ {
+ source.CreateAttribute(null, name, namespaceUri, "");
+ source.MoveToAttribute(name, namespaceUri ?? "");
+ return source;
+ }
+
+ public XPathNavigator AppendElement(string name, string namespaceUri, XPathNavigator source)
+ {
+ namespaceUri = GetEffectiveNamespace(namespaceUri);
+ source.AppendChildElement(LookupPrefix(namespaceUri), name, namespaceUri, "");
+ return source.SelectSingleNode("*[position()=last()]");
+ }
+
+ public void SetXmlType(string name, string namespaceUri, XPathNavigator source)
+ {
+ namespaceUri = GetEffectiveNamespace(namespaceUri);
+ var prefix = CreateNamespace(null, namespaceUri, source);
+ source.CreateAttribute("xsi", "type", Xsi, GetQualifiedName(prefix, name));
+ }
+
+ public XmlQualifiedName GetXmlType(XPathNavigator source)
+ {
+ var qualifiedType = source.GetAttribute("type", Xsi);
+ if (string.IsNullOrEmpty(qualifiedType) == false)
+ {
+ string name, namespaceUri = null;
+ var prefix = SplitQualifiedName(qualifiedType, out name);
+ if (prefix != null)
+ namespaceUri = source.GetNamespace(prefix);
+ return new XmlQualifiedName(name, namespaceUri);
+ }
+ return null;
+ }
+
+ public string GetEffectiveNamespace(string namespaceUri)
+ {
+ return namespaceUri ?? DefaultNamespace;
+ }
+
+ public override int CompareDocument(string baseUri, string nextbaseUri)
+ {
+ return 0;
+ }
+
+ public override bool Whitespace
+ {
+ get { return true; }
+ }
+
+ public override bool PreserveWhitespace(XPathNavigator node)
+ {
+ return true;
+ }
+
+ private string GetUniquePrefix()
+ {
+ if (parent != null)
+ return parent.GetUniquePrefix();
+ return "da" + ++prefixCount;
+ }
+
+ private static string GetQualifiedName(string prefix, string name)
+ {
+ if (string.IsNullOrEmpty(prefix))
+ return name;
+ return String.Format("{0}:{1}", prefix, name);
+ }
+
+ private static string SplitQualifiedName(string qualifiedName, out string name)
+ {
+ var parts = qualifiedName.Split(':');
+ if (parts.Length == 1)
+ {
+ name = parts[0];
+ return null;
+ }
+ else if (parts.Length == 2)
+ {
+ name = parts[1];
+ return parts[0];
+ }
+ throw new ArgumentException(string.Format(
+ "Invalid qualified name {0}. Expected [prefix:]name format", qualifiedName));
+ }
+
+ #region Nested Type: XPathVariable
+
+ public class XPathVariable : IXsltContextVariable
+ {
+ private readonly string name;
+
+ public XPathVariable(string name)
+ {
+ this.name = name;
+ }
+
+ public bool IsLocal
+ {
+ get { return false; }
+ }
+
+ public bool IsParam
+ {
+ get { return false; }
+ }
+
+ public XPathResultType VariableType
+ {
+ get { return XPathResultType.Any; }
+ }
+
+ public object Evaluate(XsltContext xsltContext)
+ {
+ var args = ((XPathContext)xsltContext).Arguments;
+ return args.GetParam(name, null);
+ }
+ }
+
+ #endregion
+
+ #region Nested Type: MatchFunction
+
+ public class MatchFunction : IXsltContextFunction
+ {
+ public static readonly MatchFunction Instance = new MatchFunction();
+
+ protected MatchFunction()
+ {
+ }
+
+ public int Minargs
+ {
+ get { return 1; }
+ }
+
+ public int Maxargs
+ {
+ get { return 2; }
+ }
+
+ public XPathResultType[] ArgTypes
+ {
+ get { return new[] { XPathResultType.String, XPathResultType.String }; }
+ }
+
+ public XPathResultType ReturnType
+ {
+ get { return XPathResultType.Boolean; }
+ }
+
+ public object Invoke(XsltContext xsltContext, object[] args, XPathNavigator docContext)
+ {
+ var key = (string)args[0];
+ if (key.Equals(docContext.LocalName, StringComparison.OrdinalIgnoreCase) == false)
+ {
+ return false;
+ }
+
+ if (args.Length > 1 && args[1].Equals(IgnoreNamespace) == false)
+ {
+ var ns = (string)args[1];
+ if (ns.Equals(docContext.NamespaceURI, StringComparison.OrdinalIgnoreCase) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ #endregion
+ }
+#endif
+}
\ No newline at end of file
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathExtensions.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathExtensions.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathExtensions.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathExtensions.cs Sun Feb 13 19:31:33 2011
@@ -0,0 +1,78 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+ using System;
+ using System.Linq;
+ using System.Xml;
+
+ internal static class XPathExtensions
+ {
+ private const string XmlMetaKey = "XmlMeta";
+
+ public static XmlMetadata GetXmlMeta(this IDictionaryAdapter dictionaryAdapter)
+ {
+ return GetXmlMeta(dictionaryAdapter, null);
+ }
+
+ public static XmlMetadata GetXmlMeta(this IDictionaryAdapter dictionaryAdapter, Type otherType)
+ {
+ if (otherType == null || otherType.IsInterface)
+ {
+ var meta = GetDictionaryMeta(dictionaryAdapter, otherType);
+ return (XmlMetadata)meta.ExtendedProperties[XmlMetaKey];
+ }
+ return null;
+ }
+
+ internal static XmlMetadata GetXmlMeta(this DictionaryAdapterMeta dictionaryAdapterMeta)
+ {
+ return (XmlMetadata)dictionaryAdapterMeta.ExtendedProperties[XmlMetaKey];
+ }
+
+ internal static void SetXmlMeta(this DictionaryAdapterMeta dictionaryAdapterMeta, XmlMetadata xmlMeta)
+ {
+ dictionaryAdapterMeta.ExtendedProperties[XmlMetaKey] = xmlMeta;
+ }
+
+ public static Type GetXmlSubclass(this IDictionaryAdapter dictionaryAdapter, XmlQualifiedName xmlType, Type otherType)
+ {
+ if (xmlType == null) return null;
+ var xmlIncludes = dictionaryAdapter.GetXmlMeta(otherType).XmlIncludes;
+ if (xmlIncludes != null)
+ {
+ var subClass = from xmlInclude in xmlIncludes
+ let xmlIncludeType = dictionaryAdapter.GetXmlMeta(xmlInclude).XmlType
+ where xmlIncludeType.TypeName == xmlType.Name &&
+ xmlIncludeType.Namespace == xmlType.Namespace
+ select xmlInclude;
+ return subClass.FirstOrDefault();
+
+ }
+ return null;
+ }
+
+ private static DictionaryAdapterMeta GetDictionaryMeta(IDictionaryAdapter dictionaryAdapter, Type otherType)
+ {
+ var meta = dictionaryAdapter.Meta;
+ if (otherType != null && otherType != meta.Type)
+ {
+ meta = dictionaryAdapter.This.Factory.GetAdapterMeta(otherType,
+ new DictionaryDescriptor().AddBehavior(XPathBehavior.Instance));
+ }
+ return meta;
+ }
+ }
+}
diff -r -u -N -w nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathResult.cs nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathResult.cs
--- nmock3-62490-original\MAIN\Source\Castle\Components.DictionaryAdapter\XPathResult.cs Thu Jan 01 01:00:00 1970
+++ nmock3-62490\MAIN\Source\Castle\Components.DictionaryAdapter\XPathResult.cs Sun Feb 13 19:31:39 2011
@@ -0,0 +1,405 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Components.DictionaryAdapter
+{
+#if !SILVERLIGHT
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using System.Xml.XPath;
+
+ internal class XPathResult
+ {
+ public readonly bool CanWrite;
+ public readonly PropertyDescriptor Property;
+ private readonly object matchingBehavior;
+ private readonly Func create;
+
+ public XPathResult(PropertyDescriptor property, object result,
+ XPathContext context, object matchingBehavior)
+ : this(property, result, context, matchingBehavior, null)
+ {
+ }
+
+ public XPathResult(Type type, object result, XPathContext context, object matchingBehavior)
+ : this(null, result, context, matchingBehavior, null)
+ {
+ Type = type;
+ }
+
+ public XPathResult(PropertyDescriptor property, object result, XPathContext context,
+ object matchingBehavior, Func create)
+ {
+ Result = result;
+ Property = property;
+ Type = (property != null) ? Property.PropertyType : null;
+ Context = context;
+ this.create = create;
+ this.matchingBehavior = matchingBehavior;
+ CanWrite = (create != null || result is XPathNavigator);
+ }
+
+ public bool IsContainer
+ {
+ get { return matchingBehavior == null || matchingBehavior is XmlArrayAttribute; }
+ }
+
+ public Type Type { get; private set; }
+
+ public object Result { get; private set; }
+
+ public XPathContext Context { get; private set; }
+
+ public XPathNavigator Container { get; private set; }
+
+ public XmlMetadata XmlMeta { get; private set; }
+
+ public bool OmitPolymorphism { get; private set; }
+
+ public XPathNavigator GetNavigator(bool demand)
+ {
+ if (Result is XPathNavigator)
+ {
+ return (XPathNavigator)Result;
+ }
+ else if (Result is XPathNodeIterator)
+ {
+ return ((XPathNodeIterator)Result).Cast().FirstOrDefault();
+ }
+ if (demand && create != null)
+ {
+ var result = create();
+ Result = result;
+ return result;
+ }
+ return null;
+ }
+
+ public XPathResult GetNodeAt(Type type, int index)
+ {
+ var node = Container;
+ if (IsContainer)
+ {
+ if (node != null)
+ {
+ node = Container.SelectSingleNode(String.Format("*[position()={0}]", index + 1));
+ }
+ }
+ else if (Result is XPathNodeIterator)
+ {
+ var nodes = ((XPathNodeIterator)Result).Cast().ToArray();
+ node = nodes[index];
+ }
+ return new XPathResult(type, node, Context, matchingBehavior);
+ }
+
+ public IEnumerable