merge mods to pull 6 for SPRNET-1470, SPRNET-1471
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user