merge mods to pull 6 for SPRNET-1470, SPRNET-1471

This commit is contained in:
Steve Bohlen
2011-11-15 11:11:09 -05:00
parent aecb61fa54
commit 43516e6dbe
6 changed files with 240 additions and 8 deletions

View File

@@ -28,6 +28,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using Spring.Util;
using System.Reflection;
#endregion
@@ -116,6 +117,45 @@ namespace Spring.Core.TypeConversion
return ToTypedCollectionWithTypeConversion(typeof(List<>), componentType, elements, propertyName);
}
}
// if required type is some IDictionary<K,V>, convert all the elements
if (requiredType != null && requiredType.IsGenericType && TypeImplementsGenericInterface(requiredType, typeof(IDictionary<,>)))
{
Type[] typeParameters = requiredType.GetGenericArguments();
Type keyType = typeParameters[0];
Type valueType = typeParameters[1];
if (newValue is IDictionary)
{
IDictionary elements = (IDictionary)newValue;
Type targetCollectionType = typeof(Dictionary<,>);
Type collectionType = targetCollectionType.MakeGenericType(new Type[] { keyType, valueType });
object typedCollection = Activator.CreateInstance(collectionType);
MethodInfo addMethod = collectionType.GetMethod("Add", new Type[] { keyType, valueType });
int i = 0;
foreach (DictionaryEntry entry in elements)
{
string propertyExpr = BuildIndexedPropertyName(propertyName, i);
object key = ConvertValueIfNecessary(keyType, entry.Key, propertyExpr + ".Key");
object value = ConvertValueIfNecessary(valueType, entry.Value, propertyExpr + ".Value");
addMethod.Invoke(typedCollection, new object[] { key, value });
i++;
}
return typedCollection;
}
}
// if required type is some IEnumerable<T>, convert all the elements
if (requiredType != null && requiredType.IsGenericType && TypeImplementsGenericInterface(requiredType, typeof(IEnumerable<>)))
{
// convert individual elements to array elements
Type componentType = requiredType.GetGenericArguments()[0];
if (newValue is ICollection)
{
ICollection elements = (ICollection)newValue;
return ToTypedCollectionWithTypeConversion(typeof(List<>), componentType, elements, propertyName);
}
}
#endif
// try to convert using type converter
@@ -289,18 +329,16 @@ namespace Spring.Core.TypeConversion
throw new ArgumentException("matchingInterface Type must be an Interface Type", "matchingInterface");
}
bool match = false;
if (candidateType.IsInterface && IsMatchingGenericInterface(candidateType, matchingInterface))
{
return true;
}
bool match = false;
Type[] implementedInterfaces = candidateType.GetInterfaces();
foreach (Type interfaceType in implementedInterfaces)
{
if (false == interfaceType.IsGenericType)
{
continue;
}
Type genericType = interfaceType.GetGenericTypeDefinition();
if (genericType == matchingInterface)
if (IsMatchingGenericInterface(interfaceType, matchingInterface))
{
match = true;
break;
@@ -309,6 +347,11 @@ namespace Spring.Core.TypeConversion
return match;
}
private static bool IsMatchingGenericInterface(Type candidateInterfaceType, Type matchingGenericInterface)
{
return candidateInterfaceType.IsGenericType && candidateInterfaceType.GetGenericTypeDefinition() == matchingGenericInterface;
}
#endif
}
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<objects xmlns="http://www.springframework.net">
<object id="HasGenericIListProperty" type="Spring.Objects.TestObject, Spring.Core.Tests">
<property name="SomeGenericIListInt32">
<list>
<value>123</value>
<value>234</value>
<value>345</value>
</list>
</property>
</object>
<object id="HasGenericIDictionaryProperty" type="Spring.Objects.TestObject, Spring.Core.Tests">
<property name="SomeGenericIDictionaryStringInt32">
<dictionary>
<entry key="aaa" value="111"/>
<entry key="bbb" value="222"/>
<entry key="ccc" value="333"/>
</dictionary>
</property>
</object>
<object id="HasGenericIEnumerableProperty" type="Spring.Objects.TestObject, Spring.Core.Tests">
<property name="SomeGenericIEnumerableInt32">
<list>
<value>123</value>
</list>
</property>
</object>
</objects>

View File

@@ -0,0 +1,131 @@
#region License
/*
* Copyright <20> 2002-2011 the original author or authors.
*
* 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.
*/
#endregion
#region Imports
using NUnit.Framework;
using Spring.Objects.Factory.Support;
using System.Collections;
using Spring.Core.TypeConversion;
using System.Collections.Generic;
using System.Collections.Specialized;
#endregion
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Unit and integration tests for collection conversion support
/// </summary>
/// <author>Choy Rim</author>
[TestFixture]
[Description("SPRNET-1470 Setting property of type IList<T> using <list/> without the @element-type specified fails.")]
public class CollectionConversionGenericTests
{
private DefaultListableObjectFactory objectFactory;
[SetUp]
public void SetUp()
{
this.objectFactory = new DefaultListableObjectFactory();
IObjectDefinitionReader reader = new XmlObjectDefinitionReader(this.objectFactory);
reader.LoadObjectDefinitions(new ReadOnlyXmlTestResource("collectionConversionGeneric.xml", GetType()));
}
[Test]
public void ShouldConvertListToGenericIList()
{
TestObject to = (TestObject)this.objectFactory.GetObject("HasGenericIListProperty");
IList<int> list = to.SomeGenericIListInt32;
Assert.That(list.Count, Is.EqualTo(3));
Assert.That(list[0], Is.EqualTo(123));
Assert.That(list[1], Is.EqualTo(234));
Assert.That(list[2], Is.EqualTo(345));
}
[Test]
public void ShouldConvertDictionaryToGenericIDictionary()
{
TestObject to = (TestObject)this.objectFactory.GetObject("HasGenericIDictionaryProperty");
IDictionary<string, int> dict = to.SomeGenericIDictionaryStringInt32;
Assert.That(dict.Count, Is.EqualTo(3));
Assert.That(dict["aaa"], Is.EqualTo(111));
Assert.That(dict["bbb"], Is.EqualTo(222));
Assert.That(dict["ccc"], Is.EqualTo(333));
}
[Test]
public void ShouldConvertListToGenericIEnumerable()
{
TestObject to = (TestObject)this.objectFactory.GetObject("HasGenericIEnumerableProperty");
IEnumerable<int> enumerable = to.SomeGenericIEnumerableInt32;
int enumerableLength = 0;
int first = 0;
foreach (int i in enumerable)
{
enumerableLength += 1;
if (enumerableLength == 1)
{
first = i;
}
}
Assert.That(enumerableLength, Is.EqualTo(1));
Assert.That(first, Is.EqualTo(123));
}
[Test]
public void ConvertArrayListToGenericIList()
{
ArrayList xs = new ArrayList();
xs.Add("Mark Pollack");
object ys = TypeConversionUtils.ConvertValueIfNecessary(typeof(IList<string>), xs, "ignored");
Assert.That(ys as IList<string>, Is.Not.Null);
IList<string> zs = (IList<string>)ys;
Assert.That(zs[0], Is.EqualTo("Mark Pollack"));
}
[Test]
public void ConvertHybridDictionaryToGenericIDictionary()
{
HybridDictionary xs = new HybridDictionary();
xs.Add("first", 1);
object ys = TypeConversionUtils.ConvertValueIfNecessary(typeof(IDictionary<string, int>), xs, "ignored");
Assert.That(ys as IDictionary<string, int>, Is.Not.Null);
IDictionary<string, int> zs = (IDictionary<string, int>)ys;
Assert.That(zs["first"], Is.EqualTo(1));
}
[Test]
public void ConvertArrayListToGenericIEnumerable()
{
ArrayList xs = new ArrayList();
xs.Add("Mark Pollack");
object ys = TypeConversionUtils.ConvertValueIfNecessary(typeof(IEnumerable<string>), xs, "ignored");
Assert.That(ys as IEnumerable<string>, Is.Not.Null);
IEnumerable<string> zs = (IEnumerable<string>)ys;
IEnumerator<string> zse = zs.GetEnumerator();
Assert.That(zse.MoveNext(), Is.True);
Assert.That(zse.Current, Is.EqualTo("Mark Pollack"));
}
}
}

View File

@@ -273,6 +273,27 @@ namespace Spring.Objects
set { this.someGenericStringList = value; }
}
private IList<int> someGenericIListInt32;
public virtual IList<int> SomeGenericIListInt32
{
get { return someGenericIListInt32; }
set { someGenericIListInt32 = value; }
}
private IDictionary<string, int> someGenericIDictionaryStringInt32;
public virtual IDictionary<string, int> SomeGenericIDictionaryStringInt32
{
get { return someGenericIDictionaryStringInt32; }
set { someGenericIDictionaryStringInt32 = value; }
}
private IEnumerable<int> someGenericIEnumerableInt32;
public virtual IEnumerable<int> SomeGenericIEnumerableInt32
{
get { return someGenericIEnumerableInt32; }
set { someGenericIEnumerableInt32 = value; }
}
public virtual NameValueCollection SomeNameValueCollection
{
get { return someNameValueCollection; }

View File

@@ -343,6 +343,7 @@
<Compile Include="Objects\Factory\Xml\ArrayCtorDependencyObject.cs" />
<Compile Include="Objects\Factory\Xml\CollectionMergingTests.cs" />
<Compile Include="Objects\Factory\Xml\CollectionMergingGenericTests.cs" />
<Compile Include="Objects\Factory\Xml\CollectionConversionGenericTests.cs" />
<Compile Include="Objects\Factory\Xml\LocaleTests.cs" />
<Compile Include="Objects\Factory\Xml\NamespaceParserRegistryTests.cs" />
<Compile Include="Objects\Factory\Xml\ObjectFactorySectionHandlerTests.cs" />
@@ -818,6 +819,7 @@
<Content Include="Data\Spring\Objects\Factory\Xml\array-autowire.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMergingGeneric.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMerging.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionConversionGeneric.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\ctor-args.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\objectNameGeneration.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\simple-constructor-arg.xml" />

View File

@@ -352,6 +352,7 @@
<Compile Include="Objects\Factory\Xml\ArrayCtorDependencyObject.cs" />
<Compile Include="Objects\Factory\Xml\CollectionMergingTests.cs" />
<Compile Include="Objects\Factory\Xml\CollectionMergingGenericTests.cs" />
<Compile Include="Objects\Factory\Xml\CollectionConversionGenericTests.cs" />
<Compile Include="Objects\Factory\Xml\LocaleTests.cs" />
<Compile Include="Objects\Factory\Xml\NamespaceParserRegistryTests.cs" />
<Compile Include="Objects\Factory\Xml\ObjectFactorySectionHandlerTests.cs" />
@@ -827,6 +828,7 @@
<Content Include="Data\Spring\Objects\Factory\Xml\array-autowire.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMergingGeneric.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMerging.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionConversionGeneric.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\ctor-args.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\objectNameGeneration.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\simple-constructor-arg.xml" />