Support type alias resolution in <value/> element [SPRNET-1119]
This commit is contained in:
@@ -21,122 +21,193 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Objects.Factory.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Holder for a typed <see cref="System.String"/> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Can be added to object definitions to explicitly specify
|
||||
/// a target type for a <see cref="System.String"/> value,
|
||||
/// for example for collection
|
||||
/// elements.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// This holder just stores the <see cref="System.String"/> value and the target
|
||||
/// <see cref="System.Type"/>. The actual conversion will be performed by
|
||||
/// the surrounding object factory.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Rick Evans (.NET)</author>
|
||||
[Serializable]
|
||||
public class TypedStringValue
|
||||
{
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
public TypedStringValue()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypedStringValue"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public TypedStringValue(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The value that is to be converted.
|
||||
/// </param>
|
||||
/// <param name="targetType">
|
||||
/// The <see cref="System.Type"/> to convert to.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="targetType"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
public TypedStringValue(string value, Type targetType)
|
||||
{
|
||||
Value = value;
|
||||
TargetType = targetType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The value that is to be converted.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Obviously if the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue.TargetType"/>
|
||||
/// is the <see cref="System.String"/> <see cref="System.Type"/>, no conversion
|
||||
/// will actually be performed.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public string Value
|
||||
{
|
||||
get { return theValue; }
|
||||
set { this.theValue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Type"/> to convert to.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the setter is supplied with a <see langword="null"/> value.
|
||||
/// </exception>
|
||||
public Type TargetType
|
||||
{
|
||||
get { return targetType; }
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(value, "TargetType");
|
||||
targetType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has target type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has target type; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool HasTargetType
|
||||
{
|
||||
get { return targetType != null; }
|
||||
}
|
||||
|
||||
private string theValue;
|
||||
private Type targetType;
|
||||
}
|
||||
using Spring.Util;
|
||||
using Spring.Core.TypeResolution;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Objects.Factory.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Holder for a typed <see cref="System.String"/> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Can be added to object definitions to explicitly specify
|
||||
/// a target type for a <see cref="System.String"/> value,
|
||||
/// for example for collection
|
||||
/// elements.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// This holder just stores the <see cref="System.String"/> value and the target
|
||||
/// <see cref="System.Type"/>. The actual conversion will be performed by
|
||||
/// the surrounding object factory.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Rick Evans (.NET)</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[Serializable]
|
||||
public class TypedStringValue
|
||||
{
|
||||
private string theValue;
|
||||
private object targetType;
|
||||
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
public TypedStringValue()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypedStringValue"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public TypedStringValue(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The value that is to be converted.
|
||||
/// </param>
|
||||
/// <param name="targetType">
|
||||
/// The <see cref="System.Type"/> to convert to.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="targetType"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
public TypedStringValue(string value, Type targetType)
|
||||
{
|
||||
Value = value;
|
||||
TargetType = targetType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The value that is to be converted.
|
||||
/// </param>
|
||||
/// <param name="targetTypeName">
|
||||
/// The unresolved type to convert to.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="targetTypeName"/> is a
|
||||
/// <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
public TypedStringValue(string value, string targetTypeName)
|
||||
{
|
||||
Value = value;
|
||||
TargetTypeName = targetTypeName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The value that is to be converted.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Obviously if the
|
||||
/// <see cref="Spring.Objects.Factory.Config.TypedStringValue.TargetType"/>
|
||||
/// is the <see cref="System.String"/> <see cref="System.Type"/>, no conversion
|
||||
/// will actually be performed.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public string Value
|
||||
{
|
||||
get { return theValue; }
|
||||
set { this.theValue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Type"/> to convert to.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the setter is supplied with a <see langword="null"/> value.
|
||||
/// </exception>
|
||||
public Type TargetType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!HasTargetType)
|
||||
{
|
||||
throw new ApplicationException(
|
||||
"Typed String value does not carry a resolved System.Type");
|
||||
}
|
||||
return (Type)targetType;
|
||||
}
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(value, "TargetType");
|
||||
targetType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The unresolved type to convert to.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the setter is supplied with a <see langword="null"/> value or an empty string.
|
||||
/// </exception>
|
||||
public string TargetTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (targetType is Type)
|
||||
{
|
||||
return ((Type) targetType).FullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return targetType as string;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentHasText(value, "TargetTypeName");
|
||||
targetType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has target type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has target type; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool HasTargetType
|
||||
{
|
||||
get { return targetType is Type; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the type to convert to, resolving it from a specified type name if necessary.
|
||||
/// </summary>
|
||||
/// <returns>The resolved type to convert to.</returns>
|
||||
public Type ResolveTargetType()
|
||||
{
|
||||
if (this.targetType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Type resolvedType = TypeResolutionUtils.ResolveType(this.TargetTypeName);
|
||||
this.targetType = resolvedType;
|
||||
return resolvedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,14 +239,11 @@ namespace Spring.Objects.Factory.Support
|
||||
/// <returns>The resolved target type, if any. <see lang="null" /> otherwise.</returns>
|
||||
protected virtual Type ResolveTargetType(TypedStringValue value)
|
||||
{
|
||||
if (value.HasTargetType)
|
||||
if (value.HasTargetType)
|
||||
{
|
||||
return value.TargetType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
return value.TargetType;
|
||||
}
|
||||
return value.ResolveTargetType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1003,15 +1003,7 @@ namespace Spring.Objects.Factory.Xml
|
||||
}
|
||||
else
|
||||
{
|
||||
Type resolvedValueType = TypeResolutionUtils.ResolveType(valueType);
|
||||
if (resolvedValueType == typeof(string))
|
||||
{
|
||||
return ParseTextValueElement(element, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TypedStringValue(ParseTextValueElement(element, name), resolvedValueType);
|
||||
}
|
||||
return new TypedStringValue(ParseTextValueElement(element, name), valueType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<property name="TypeAliases">
|
||||
<dictionary>
|
||||
<entry key="TestObject" value="Spring.Objects.TestObject, Spring.Core.Tests" />
|
||||
<entry key="intAlias" value="System.Int32" />
|
||||
</dictionary>
|
||||
</property>
|
||||
</object>
|
||||
@@ -19,4 +20,12 @@
|
||||
<constructor-arg name="age" value="26"/>
|
||||
</object>
|
||||
|
||||
<!-- SPRNET-1119 -->
|
||||
<object id="testObject4" type="TestObject">
|
||||
<constructor-arg name="name" value="Bruno"/>
|
||||
<constructor-arg name="age">
|
||||
<value type="intAlias">30</value>
|
||||
</constructor-arg>
|
||||
</object>
|
||||
|
||||
</objects>
|
||||
@@ -124,6 +124,13 @@ namespace Spring.Objects.Factory.Config
|
||||
Assert.AreEqual(typeof(TestObject), obj3.GetType());
|
||||
Assert.AreEqual("Bruno", ((TestObject)obj3).Name);
|
||||
Assert.AreEqual(26, ((TestObject)obj3).Age);
|
||||
|
||||
// SPRNET-1119
|
||||
object obj4 = ctx.GetObject("testObject4");
|
||||
Assert.IsNotNull(obj4);
|
||||
Assert.AreEqual(typeof(TestObject), obj4.GetType());
|
||||
Assert.AreEqual("Bruno", ((TestObject)obj4).Name);
|
||||
Assert.AreEqual(30, ((TestObject)obj4).Age);
|
||||
}
|
||||
|
||||
private void CreateConfigurerAndTestLinkedList(IDictionary typeAliases)
|
||||
|
||||
@@ -40,20 +40,41 @@ namespace Spring.Objects.Factory.Config
|
||||
public void Instantiation()
|
||||
{
|
||||
string expectedNow = DateTime.Now.ToShortDateString();
|
||||
TypedStringValue tsv = new TypedStringValue(expectedNow, typeof (DateTime));
|
||||
|
||||
TypedStringValue tsv = new TypedStringValue(expectedNow, typeof (DateTime));
|
||||
Assert.AreEqual(expectedNow, tsv.Value);
|
||||
Assert.AreEqual(typeof (DateTime), tsv.TargetType);
|
||||
|
||||
tsv = new TypedStringValue(expectedNow);
|
||||
Assert.AreEqual(expectedNow, tsv.Value);
|
||||
|
||||
tsv = new TypedStringValue(expectedNow, typeof(DateTime).FullName);
|
||||
Assert.AreEqual(expectedNow, tsv.Value);
|
||||
Assert.AreEqual(typeof(DateTime).FullName, tsv.TargetTypeName);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof (ArgumentNullException))]
|
||||
public void InstantiationWithNullType()
|
||||
{
|
||||
new TypedStringValue(string.Empty, null);
|
||||
new TypedStringValue(string.Empty, (Type)null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void InstantiationWithNullTypeName()
|
||||
{
|
||||
new TypedStringValue(string.Empty, (string)null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void InstantiationWithEmptyTypeName()
|
||||
{
|
||||
new TypedStringValue(string.Empty, " ");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof (ArgumentNullException))]
|
||||
public void SetTargetTypePropertyToNullType()
|
||||
@@ -62,6 +83,14 @@ namespace Spring.Objects.Factory.Config
|
||||
tsv.TargetType = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void SetTargetTypeNamePropertyToEmptyString()
|
||||
{
|
||||
TypedStringValue tsv = new TypedStringValue(string.Empty, typeof(DateTime));
|
||||
tsv.TargetTypeName = " ";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSerializable()
|
||||
{
|
||||
@@ -88,5 +117,33 @@ namespace Spring.Objects.Factory.Config
|
||||
Assert.AreEqual(expectedValue, deser.Value,
|
||||
"Serialization roundtrip yielded the wrong Value.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasTargetType()
|
||||
{
|
||||
TypedStringValue tsv = new TypedStringValue(string.Empty, typeof(DateTime));
|
||||
Assert.IsTrue(tsv.HasTargetType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasTargetTypeReturnsFalseWhenTargetTypeNotResolved()
|
||||
{
|
||||
TypedStringValue tsv = new TypedStringValue(string.Empty, typeof(DateTime).FullName);
|
||||
Assert.IsFalse(tsv.HasTargetType);
|
||||
|
||||
tsv = new TypedStringValue(string.Empty, typeof(DateTime));
|
||||
Assert.IsTrue(tsv.HasTargetType);
|
||||
tsv.TargetTypeName = typeof(DateTime).FullName;
|
||||
Assert.IsFalse(tsv.HasTargetType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResolveTargetType()
|
||||
{
|
||||
TypedStringValue tsv = new TypedStringValue(string.Empty, typeof(DateTime).FullName);
|
||||
Assert.IsFalse(tsv.HasTargetType);
|
||||
Assert.AreEqual(typeof(DateTime), tsv.ResolveTargetType());
|
||||
Assert.IsTrue(tsv.HasTargetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user