Update of /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18183/Spring/Spring.Core/Objects
Modified Files:
FatalObjectException.cs IObjectWrapper.cs
MutablePropertyValues.cs NotWritablePropertyException.cs
ObjectUtils.cs ObjectWrapper.cs ObjectsException.cs
PropertyChangeEventArgs.cs PropertyValue.cs
TypeMismatchException.cs
Log Message:
Added centralised Type resolution mechanism, runtime type converter, Xml Config handler, multiple documentation updates.
Index: FatalObjectException.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/FatalObjectException.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** FatalObjectException.cs 3 May 2004 10:26:28 -0000 1.2
--- FatalObjectException.cs 26 Jul 2004 07:47:55 -0000 1.3
***************
*** 18,23 ****
namespace Spring.Objects
{
! /// <summary> Thrown on an unrecoverable problem encountered in the
! /// beans packages or sub-packages, e.g. bad class or field.
/// </summary>
/// <author>Rod Johnson</author>
--- 18,24 ----
namespace Spring.Objects
{
! /// <summary>
! /// Thrown on an unrecoverable problem encountered in the
! /// objects namespace or sub-namespaces, e.g. bad class or field.
/// </summary>
/// <author>Rod Johnson</author>
Index: PropertyValue.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/PropertyValue.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** PropertyValue.cs 3 May 2004 10:26:28 -0000 1.1
--- PropertyValue.cs 26 Jul 2004 07:47:55 -0000 1.2
***************
*** 14,32 ****
* limitations under the License.
*/
using System;
namespace Spring.Objects
{
! /// <summary> Class to hold information and value for an individual property.
/// Using an object here, rather than just storing all properties in a
/// map keyed by property name, allows for more flexibility, and the
/// ability to handle indexed properties etc in a special way if necessary.
- ///
- /// <p>Note that the value doesn't need to be the final required type:
- /// A ObjectWrapper implementation should handle any necessary conversion, as
- /// this object doesn't know anything about the objects it will be applied to.
/// </p>
! ///
! /// </summary>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
--- 14,39 ----
* limitations under the License.
*/
+
using System;
+
namespace Spring.Objects
{
! /// <summary>
! /// Class to hold information and value for an individual property.
! /// </summary>
! /// <remarks>
! /// <p>
/// Using an object here, rather than just storing all properties in a
/// map keyed by property name, allows for more flexibility, and the
/// ability to handle indexed properties etc in a special way if necessary.
/// </p>
! /// <p>
! /// Note that the value doesn't need to be the final required type:
! /// A <see cref="Spring.Objects.IObjectWrapper"/> implementation should
! /// handle any necessary conversion, as this object doesn't know anything
! /// about the objects it will be applied to.
! /// </p>
! /// </remarks>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
***************
*** 34,40 ****
public class PropertyValue
{
! /// <summary> Return the name of the property.</summary>
! /// <returns> the name of the property
! /// </returns>
virtual public string Name
{
--- 41,46 ----
public class PropertyValue
{
! /// <summary>Gets the name of the property.</summary>
! /// <returns>The name of the property.</returns>
virtual public string Name
{
***************
*** 45,55 ****
}
! /// <summary> Return the value of the property.
! /// <p>Note that type conversion will <i>not</i> have occurred here.
! /// It is the responsibility of the BeanWrapper implementation to
! /// perform type conversion.</p>
/// </summary>
! /// <returns> the value of the property
! /// </returns>
virtual public object Value
{
--- 51,66 ----
}
! /// <summary>
! /// Return the value of the property.
/// </summary>
! /// <remarks>
! /// <p>
! /// Note that type conversion will <i>not</i> have occurred here.
! /// It is the responsibility of the
! /// <see cref="Spring.Objects.IObjectWrapper"/> implementation to
! /// perform type conversion.
! /// </p>
! /// </remarks>
! /// <returns>The value of the property.</returns>
virtual public object Value
{
***************
*** 67,80 ****
private object _val;
! /// <summary> Creates new PropertyValue.</summary>
! /// <param name="name">name of the property
! /// </param>
! /// <param name="val">value of the property (possibly before type conversion)
/// </param>
! public PropertyValue(string name, object val)
{
! if ((object) name == null)
{
! throw new System.ArgumentException("Property name cannot be null");
}
_name = name;
--- 78,93 ----
private object _val;
! /// <summary>
! /// Creates a new instance of the PropertyValue class.
! /// </summary>
! /// <param name="name">The name of the property.</param>
! /// <param name="val">
! /// The value of the property (possibly before type conversion).
/// </param>
! public PropertyValue (string name, object val)
{
! if (name == null)
{
! throw new ArgumentNullException ("Property name cannot be null");
}
_name = name;
***************
*** 83,93 ****
/// <summary>
! /// Print a string representation of the property
/// </summary>
! /// <returns></returns>
! public override string ToString()
{
! //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1043_3"'
! return "PropertyValue: name='" + _name + "'; value=[" + _val + "]";
}
--- 96,105 ----
/// <summary>
! /// Print a string representation of the property.
/// </summary>
! /// <returns>A string representation of the property.</returns>
! public override string ToString ()
{
! return string.Format ("PropertyValue: name='{0}'; value=[{1}].", _name, _val);
}
***************
*** 95,101 ****
/// Test if another object is equal in value to this one.
/// </summary>
! /// <param name="other">the other instance</param>
! /// <returns>true if they are equal in content, false otherwise</returns>
! public override bool Equals(object other)
{
if (this == other)
--- 107,113 ----
/// Test if another object is equal in value to this one.
/// </summary>
! /// <param name="other">The other instance.</param>
! /// <returns>True if they are equal in content, false otherwise.</returns>
! public override bool Equals (object other)
{
if (this == other)
***************
*** 108,112 ****
}
PropertyValue otherPv = (PropertyValue) other;
! return (_name.Equals(otherPv._name) && ((_val == null && otherPv._val == null) || _val.Equals(otherPv._val)));
}
--- 120,124 ----
}
PropertyValue otherPv = (PropertyValue) other;
! return (_name.Equals (otherPv._name) && ((_val == null && otherPv._val == null) || _val.Equals (otherPv._val)));
}
***************
*** 114,121 ****
/// The hashcode of the property
/// </summary>
! /// <returns>the hashcode of the property</returns>
public override int GetHashCode()
{
! return _name.GetHashCode() * 29 + (_val != null?_val.GetHashCode():0);
}
}
--- 126,133 ----
/// The hashcode of the property
/// </summary>
! /// <returns>The hashcode of the property.</returns>
public override int GetHashCode()
{
! return _name.GetHashCode () * 29 + (_val != null ? _val.GetHashCode () : 0);
}
}
Index: IObjectWrapper.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/IObjectWrapper.cs,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** IObjectWrapper.cs 6 Jul 2004 12:54:10 -0000 1.5
--- IObjectWrapper.cs 26 Jul 2004 07:47:55 -0000 1.6
***************
*** 138,142 ****
/// <param name="pvs">PropertyValues to set on the target object
/// </param>
! /// <param name="ignoreUnknown">should we ignore unknown values (not found in the bean!?)
/// </param>
void SetPropertyValues(IPropertyValues pvs, bool ignoreUnknown);
--- 138,142 ----
/// <param name="pvs">PropertyValues to set on the target object
/// </param>
! /// <param name="ignoreUnknown">should we ignore unknown values (not found in the object!?)
/// </param>
void SetPropertyValues(IPropertyValues pvs, bool ignoreUnknown);
Index: NotWritablePropertyException.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/NotWritablePropertyException.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** NotWritablePropertyException.cs 3 May 2004 10:26:28 -0000 1.1
--- NotWritablePropertyException.cs 26 Jul 2004 07:47:55 -0000 1.2
***************
*** 29,33 ****
/// <param name="propertyName">The name of the property that is not writable</param>
/// <param name="objectType">The type in which the property is not writable.</param>
! public NotWritablePropertyException(string propertyName, Type objectType):base("Property '" + propertyName + "' is not writable in bean class [" + objectType.FullName + "]")
{
}
--- 29,33 ----
/// <param name="propertyName">The name of the property that is not writable</param>
/// <param name="objectType">The type in which the property is not writable.</param>
! public NotWritablePropertyException(string propertyName, Type objectType):base("Property '" + propertyName + "' is not writable in object class [" + objectType.FullName + "]")
{
}
***************
*** 39,43 ****
/// <param name="objectType">The type in which the property is not writable.</param>
/// <param name="ex">The root cause indicating why the property was not writable.</param>
! public NotWritablePropertyException(string propertyName, Type objectType, System.Exception ex):base("Property '" + propertyName + "' is not writable in bean class [" + objectType.FullName + "]", ex)
{
}
--- 39,43 ----
/// <param name="objectType">The type in which the property is not writable.</param>
/// <param name="ex">The root cause indicating why the property was not writable.</param>
! public NotWritablePropertyException(string propertyName, Type objectType, System.Exception ex):base("Property '" + propertyName + "' is not writable in object class [" + objectType.FullName + "]", ex)
{
}
Index: ObjectUtils.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/ObjectUtils.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** ObjectUtils.cs 16 Jul 2004 13:59:03 -0000 1.2
--- ObjectUtils.cs 26 Jul 2004 07:47:55 -0000 1.3
***************
*** 24,27 ****
--- 24,29 ----
using System.Reflection;
+ using Spring.Util;
+
#endregion
***************
*** 34,43 ****
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public sealed class ObjectUtils
{
- #region Constants
- #endregion
-
#region Constructor (s) / Destructor
/// <summary>
--- 36,43 ----
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
+ /// <version>$Id$</version>
public sealed class ObjectUtils
{
#region Constructor (s) / Destructor
/// <summary>
***************
*** 52,99 ****
#endregion
- #region Properties
- #endregion
-
#region Methods
/// <summary>
! /// Convenience method to instantiate a type using its no-arg constructor.
! /// As this method doesn't try to instantiate types by name, it should avoid class-loading issues.
/// </summary>
! /// <param name="type">the type to instantiate</param>
! /// <exception cref="Spring.Objects.FatalObjectException"></exception>
! /// <returns>the new instance</returns>
! public static object InstantiateType(Type type)
{
try
{
! return Activator.CreateInstance(type);
}
catch (Exception e)
{
! throw new FatalObjectException("Could not instantiate type [" + type.Name +
! "]; Is it an interface or an abstract class? Does it have a no-arg constructor?", e);
}
}
/// <summary>
! /// Convenience method to instantiate a type using the given constructor.
! /// As this method doesn't try to instantiate types by name, it should avoid class-loading issues.
! ///
! /// TODO: check this uses the correct constructor.
/// </summary>
! /// <param name="constructor">constructor to instantiate</param>
! /// <param name="arguments">the arguments to be passed to the constructor</param>
! /// <returns>the new instance</returns>
! public static object InstantiateType(ConstructorInfo constructor, object[] arguments)
{
! object obj = null ;
try
{
! obj = constructor.Invoke(arguments);
}
catch (Exception e)
{
! throw new FatalObjectException("Could not instantiate type [" + constructor.DeclaringType.Name +
! "]; Is it an interface or an abstract class? Does it have a no-arg constructor?", e);
}
return obj;
--- 52,116 ----
#endregion
#region Methods
/// <summary>
! /// Convenience method to instantiate a <see cref="System.Type"/> using its no-arg constructor.
/// </summary>
! /// <remarks>
! /// <p>
! /// As this method doesn't try to instantiate types by name, it should avoid type loading issues.
! /// </p>
! /// </remarks>
! /// <param name="type">
! /// The <see cref="System.Type"/> to instantiate</param>
! /// <exception cref="Spring.Objects.FatalObjectException">
! /// If the <see cref="System.Type"/> could not be instantiated.
! /// </exception>
! /// <returns>A new instance of the <see cref="System.Type"/>.</returns>
! public static object InstantiateType (Type type)
{
try
{
! // TODO : use explicit reflection (c.f. Aleksander Seovic's recommendation)
! return Activator.CreateInstance (type);
}
catch (Exception e)
{
! throw new FatalObjectException (
! string.Format (
! "Could not instantiate type [{0}]; is it an interface or an abstract class? Does it have a no-arg constructor?", type),
! e);
}
}
/// <summary>
! /// Convenience method to instantiate a <see cref="System.Type"/> using the given constructor.
/// </summary>
! /// <remarks>
! /// <p>
! /// As this method doesn't try to instantiate types by name, it should avoid type loading issues.
! /// </p>
! /// </remarks>
! /// <param name="constructor">
! /// The constructor to use for the instantiation.
! /// </param>
! /// <param name="arguments">
! /// The arguments to be passed to the constructor.
! /// </param>
! /// <returns>A new instance.</returns>
! public static object InstantiateType (
! ConstructorInfo constructor, object[] arguments)
{
! // TODO: check this uses the correct constructor.
! object obj = null;
try
{
! obj = constructor.Invoke (arguments);
}
catch (Exception e)
{
! throw new FatalObjectException (
! string.Format (
! "Could not instantiate type [{0}]; is it an interface or an abstract class? Does it have a no-arg constructor?", constructor),
! e);
}
return obj;
***************
*** 101,167 ****
/// <summary>
! /// Converts a string into a type.
! ///
! /// TODO: seems like a silly thing to have to do, but haven't found a better way
! /// of doing it yet!
! /// </summary>
! /// <param name="s">the string to convert</param>
! /// <returns>the type, or null if the conversion could not be performed</returns>
! public static Type LocateType(string s)
! {
! if (s == null)
! {
! throw new ArgumentException("Cannot convert null to primitive type.");
! }
!
! return LocateTypeFromAssemblies(s);
! }
!
! /// <summary>
! /// Tries to locate the specified type by trying each assembly within the current domain.
! ///
! /// TODO: This must be slow (and probably a VERY wrong way of doing this!), however
! /// it works so for now live with it!!!!!!! FIX ME !!!!!!!
! /// </summary>
! /// <param name="typeName">the type to locate</param>
! /// <returns>the type, or null if the type could not be located</returns>
! private static Type LocateTypeFromAssemblies(string typeName)
! {
! Type type = null ;
! Assembly[] asses = System.AppDomain.CurrentDomain.GetAssemblies();
! foreach(Assembly ass in asses)
! {
! type = ass.GetType(typeName, false, false);
! if (type != null)
! {
! break;
! }
! }
! return type;
! }
!
! /// <summary>
! /// Determine if the given type is assignable from the given value,
! /// assuming setting by reflection. Considers primitive wrapper classes
! /// as assignable to the corresponding primitive types.
! /// For example used in a object factory's constructor resolution.
/// </summary>
! /// <param name="type">the target type</param>
! /// <param name="obj">the value that should be assigned to the type</param>
! /// <returns>if the type is assignable from the value</returns>
! public static bool IsAssignable(Type type, object obj)
{
! return (type.IsInstanceOfType(obj) ||
(!type.IsPrimitive && obj == null) ||
! (type.Equals(typeof(bool)) && obj is Boolean) ||
! (type.Equals(typeof(byte)) && obj is Byte) ||
! (type.Equals(typeof(char)) && obj is Char) ||
! (type.Equals(typeof(sbyte)) && obj is SByte) ||
! (type.Equals(typeof(int)) && obj is Int32) ||
// TODO: what to do here?
! (type.Equals(typeof(short)) && obj is Int16) ||
! (type.Equals(typeof(long)) && obj is Int64) ||
! (type.Equals(typeof(float)) && obj is Single) ||
! (type.Equals(typeof(double)) && obj is Double));
}
--- 118,150 ----
/// <summary>
! /// Determine if the given <see cref="System.Type"/> is assignable from the
! /// given value, assuming setting by reflection.
/// </summary>
! /// <remarks>
! /// <p>
! /// Considers primitive wrapper classes as assignable to the
! /// corresponding primitive types.
! /// </p>
! /// <p>
! /// For example used in an object factory's constructor resolution.
! /// </p>
! /// </remarks>
! /// <param name="type">The target <see cref="System.Type"/>.</param>
! /// <param name="obj">The value that should be assigned to the type.</param>
! /// <returns>True if the type is assignable from the value.</returns>
! public static bool IsAssignable (Type type, object obj)
{
! return (type.IsInstanceOfType (obj) ||
(!type.IsPrimitive && obj == null) ||
! (type.Equals (typeof (bool)) && obj is Boolean) ||
! (type.Equals (typeof (byte)) && obj is Byte) ||
! (type.Equals (typeof (char)) && obj is Char) ||
! (type.Equals (typeof (sbyte)) && obj is SByte) ||
! (type.Equals (typeof (int)) && obj is Int32) ||
// TODO: what to do here?
! (type.Equals (typeof(short)) && obj is Int16) ||
! (type.Equals (typeof(long)) && obj is Int64) ||
! (type.Equals (typeof(float)) && obj is Single) ||
! (type.Equals (typeof(double)) && obj is Double));
}
***************
*** 183,187 ****
return type.IsPrimitive
|| IsPrimitiveArray (type)
- || IsPrimitiveWrapperArray (type)
|| type.Equals (typeof (string))
|| type.Equals (typeof (string []))
--- 166,169 ----
***************
*** 190,194 ****
}
! /// <summary> Check if the given class represents a primitive array,
/// i.e. boolean, byte, char, short, int, long, float, or double.
/// </summary>
--- 172,177 ----
}
! /// <summary>
! /// Check if the given class represents a primitive array,
/// i.e. boolean, byte, char, short, int, long, float, or double.
/// </summary>
***************
*** 204,223 ****
|| typeof (double []).Equals (type);
}
!
! /// <summary> Check if the given class represents an array of primitive wrappers,
! /// i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double.
/// </summary>
! public static bool IsPrimitiveWrapperArray (Type type)
{
! return typeof (bool []).Equals (type)
! || typeof (sbyte []).Equals (type)
! || typeof (char []).Equals (type)
! || typeof (short []).Equals (type)
! || typeof (int []).Equals (type)
! || typeof (long []).Equals (type)
! || typeof (float []).Equals (type)
! || typeof (double []).Equals (type);
}
#endregion
}
}
--- 187,213 ----
|| typeof (double []).Equals (type);
}
!
! /// <summary>
! /// Resolves the supplied type name into a <see cref="System.Type"/>
! /// instance.
/// </summary>
! /// <param name="typeName">
! /// The (possibly partially assembly qualified) name of a <see cref="System.Type"/>.
! /// </param>
! /// <returns>
! /// A resolved <see cref="System.Type"/> instance.
! /// </returns>
! /// <exception cref="System.TypeLoadException">
! /// If the type could not be resolved.
! /// </exception>
! public static Type ResolveType (string typeName)
{
! return typeResolver.Resolve (typeName);
}
#endregion
+
+ #region Fields
+ private static TypeResolver typeResolver = new CachedTypeResolver ();
+ #endregion
}
}
Index: PropertyChangeEventArgs.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/PropertyChangeEventArgs.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** PropertyChangeEventArgs.cs 11 May 2004 22:23:32 -0000 1.2
--- PropertyChangeEventArgs.cs 26 Jul 2004 07:47:55 -0000 1.3
***************
*** 61,64 ****
}
}
-
-
--- 61,62 ----
Index: ObjectWrapper.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Core/Objects/ObjectWrapper.cs,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -d -r1.19 -r1.20
*** ObjectWrapper.cs 18 Jul 2004 09:37:00 -0000 1.19
--- ObjectWrapper.cs 26 Jul 2004 07:47:55 -0000 1.20
***************
*** 73,84 ****
private string _nestedPath = string.Empty;
! /// <summary>
/// Dictionary with cached nested ObjectWrappers
/// </summary>
private IDictionary _nestedObjectWrappers;
! /// <summary>Map with custom TypeConverter instances </summary>
private IDictionary _customConverters;
! /// <summary>
/// The default converts used to convert string to object types.
/// </summary>
private static readonly IDictionary _defaultConverters = new Hashtable ();
! /// <summary>
/// The path separator for nested properties. Moved from
/// </summary>
public const string NestedPropertySeparator = ".";
--- 73,92 ----
private string _nestedPath = string.Empty;
! /// <summary>
! /// Dictionary with cached nested ObjectWrappers
! /// </summary>
! private IDictionary _nestedObjectWrappers;
! /// <summary>Map with custom TypeConverter instances </summary>
! private IDictionary _customConverters;
! /// <summary>
! /// The default converts used to convert string to object types.
! /// </summary>
private static readonly IDictionary _defaultConverters = new Hashtable ();
! /// <summary>
! /// The path separator for nested properties. Moved from
! /// </summary>
public const string NestedPropertySeparator = ".";
***************
*** 123,142 ****
}
! /// <summary>
/// Create new ObjectWrapper for the given object, registering a nested path that
/// the object is in.
/// </summary>
/// <param name="instance">
/// The object wrapped by this ObjectWrapper.
/// </param>
/// <param name="nestedPath">
/// The nested path of the object.
/// </param>
public ObjectWrapper (object instance, string nestedPath)
{
WrappedInstance = instance;
_nestedPath = nestedPath;
}
! /// <summary>
/// Create new ObjectWrapper for the given object, instantiating a new
/// instance of the specified <see cref="System.Type"/>.
/// </summary>
/// <param name="type">
/// The <see cref="System.Type"/> to instantiate and wrap.
/// </param>
/// <exception cref="Spring.Objects.FatalObjectException">
/// If the <see cref="System.Type"/> could not be wrapped.
/// </exception>
public ObjectWrapper (Type type)
{
try
! {
WrappedInstance = Activator.CreateInstance (type);
}
! catch (Exception ex)
! {
throw new FatalObjectException (
! string.Format (
! "Could not instantiate Type [{0}]; is it an interface or an abstract class? " +
! "Does it have a no-arg constructor?",
! type.FullName,
! ex));
}
}
! /// <summary>
/// Initialize the default converters.
/// </summary>
static ObjectWrapper ()
{
_defaultConverters [typeof (string [])] = new StringArrayConverter ();
}
#endregion
--- 131,172 ----
}
! /// <summary>
! /// Create new ObjectWrapper for the given object, registering a nested path that
! /// the object is in.
! /// </summary>
! /// <param name="instance">
! /// The object wrapped by this ObjectWrapper.
! /// </param>
! /// <param name="nestedPath">
! /// The nested path of the object.
! /// </param>
! public ObjectWrapper (object instance, string nestedPath)
! {
! WrappedInstance = instance;
! _nestedPath = nestedPath;
! }
! /// <summary>
! /// Create new ObjectWrapper for the given object, instantiating a new
! /// instance of the specified <see cref="System.Type"/>.
! /// </summary>
! /// <param name="type">
! /// The <see cref="System.Type"/> to instantiate and wrap.
! /// </param>
! /// <exception cref="Spring.Objects.FatalObjectException">
! /// If the <see cref="System.Type"/> could not be wrapped.
! /// </exception>
! public ObjectWrapper (Type type)
! {
! WrappedInstance = ObjectUtils.InstantiateType (type);
! }
! /// <summary>
! /// Initialize the default converters.
! /// </summary>
static ObjectWrapper ()
{
_defaultConverters [typeof (string [])] = new StringArrayConverter ();
+ _defaultConverters [typeof (Type)] = new RuntimeTypeConverter ();
}
#endregion
***************
*** 175,181 ****
/// <summary>
! /// Convenience method to return the type of the wrapped object.
/// </summary>
! /// <returns>The type of the wrapped object.
/// </returns>
public Type WrappedType
--- 205,212 ----
/// <summary>
! /// Convenience method to return the <see cref="System.Type"/> of the wrapped object.
/// </summary>
! /// <returns>
! /// The <see cref="System.Type"/> of the wrapped object.
/// </returns>
public Type WrappedType
***************
*** 189,193 ****
#region Methods
! /// <summary>
/// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
/// for all properties of the given <see cref="System.Type"/>.
/// </summary>
/// <param name="requiredType">
/// The <see cref="System.Type"/> of property.
/// </param>
/// <param name="typeConverter">
/// The <see cref="System.ComponentModel.TypeConverter"/> to register.
/// </param>
--- 220,231 ----
#region Methods
! /// <summary>
! /// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
! /// for all properties of the given <see cref="System.Type"/>.
! /// </summary>
! /// <param name="requiredType">
! /// The <see cref="System.Type"/> of property.
! /// </param>
! /// <param name="typeConverter">
/// The <see cref="System.ComponentModel.TypeConverter"/> to register.
/// </param>
***************
*** 198,202 ****
}
! /// <summary>
/// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
/// for all properties of the given type.
/// </summary>
/// <param name="requiredType">
/// The <see cref="System.Type"/> of property.
/// </param>
/// <param name="typeConverter">
/// The <see cref="System.ComponentModel.TypeConverter"/> to register.
/// </param>
--- 236,247 ----
}
! /// <summary>
! /// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
! /// for all properties of the given <see cref="System.Type"/>.
! /// </summary>
! /// <param name="requiredType">
! /// The <see cref="System.Type"/> of property.
! /// </param>
! /// <param name="typeConverter">
/// The <see cref="System.ComponentModel.TypeConverter"/> to register.
/// </param>
***************
*** 239,249 ****
}
! /// <summary>
/// Is the property nested? That is, does it contain the nested property
/// separator (usually ".").
/// </summary>
/// <param name="path">The property path.</param>
/// <returns>True if the property is nested.</returns>
private bool IsNestedProperty (string path)
{
return path.IndexOf (NestedPropertySeparator) != - 1;
}
! /// <summary>
/// Get the last component of the path. Also works if not nested.
/// </summary>
/// <param name="nestedPath">
/// The property path we know is nested.
/// </param>
/// <returns>
/// The last component of the path (the property on the target object).
/// </returns>
private string GetFinalPath (string nestedPath)
{
return nestedPath.Substring (
nestedPath.LastIndexOf (NestedPropertySeparator) + 1);
}
! /// <summary>
/// Recursively navigate to return a <see cref="Spring.Objects.ObjectWrapper"/>
/// for the nested property path.
/// </summary>
/// <param name="propertyPath">
/// The property property path, which may be nested.
/// </param>
/// <returns>
/// A <see cref="Spring.Objects.ObjectWrapper"/> for the target object.
/// </returns>
private ObjectWrapper GetObjectWrapperForPropertyPath (string propertyPath)
{
int pos = propertyPath.IndexOf (NestedPropertySeparator);
// handle nested properties recursively
if (pos > - 1)
{
string nestedProperty = propertyPath.Substring (0, pos - 0);
string nestedPath = propertyPath.Substring (pos + 1);
ObjectWrapper nestedOw = GetNestedObjectWrapper (nestedProperty);
return nestedOw.GetObjectWrapperForPropertyPath (nestedPath);
}
else
{
return this;
}
}
! /// <summary>
/// Find a custom <see cref="System.ComponentModel.TypeConverter"/> for the
/// given <see cref="System.Type"/> and property.</summary>
/// <param name="requiredType">
/// The <see cref="System.Type"/> of the property, can be null if a property
/// is given but should be specified in any case for consistency checking.
/// </param>
/// <param name="propertyPath">
/// The path of the property (name or nested path), or null if looking for a
/// <see cref="System.ComponentModel.TypeConverter"/> for all properties of
/// the given <see cref="System.Type"/>.
/// </param>
/// <returns>
/// The registered <see cref="System.ComponentModel.TypeConverter"/>, or null
/// if none.
/// </returns>
public TypeConverter FindCustomConverter (
Type requiredType, string propertyPath)
--- 284,356 ----
}
! /// <summary>
! /// Is the property nested? That is, does it contain the nested property
! /// separator (usually ".").
! /// </summary>
! /// <param name="path">The property path.</param>
! /// <returns>True if the property is nested.</returns>
! private bool IsNestedProperty (string path)
! {
! return path.IndexOf (NestedPropertySeparator) != - 1;
! }
! /// <summary>
! /// Get the last component of the path. Also works if not nested.
! /// </summary>
! /// <param name="nestedPath">
! /// The property path we know is nested.
! /// </param>
! /// <returns>
! /// The last component of the path (the property on the target object).
! /// </returns>
! private string GetFinalPath (string nestedPath)
! {
! return nestedPath.Substring (
! nestedPath.LastIndexOf (NestedPropertySeparator) + 1);
! }
! /// <summary>
! /// Recursively navigate to return a <see cref="Spring.Objects.ObjectWrapper"/>
! /// for the nested property path.
! /// </summary>
! /// <param name="propertyPath">
! /// The property property path, which may be nested.
! /// </param>
! /// <returns>
! /// A <see cref="Spring.Objects.ObjectWrapper"/> for the target object.
! /// </returns>
! private ObjectWrapper GetObjectWrapperForPropertyPath (string propertyPath)
! {
! int pos = propertyPath.IndexOf (NestedPropertySeparator);
! // handle nested properties recursively
! if (pos > - 1)
! {
! string nestedProperty = propertyPath.Substring (0, pos - 0);
! string nestedPath = propertyPath.Substring (pos + 1);
! ObjectWrapper nestedOw = GetNestedObjectWrapper (nestedProperty);
! return nestedOw.GetObjectWrapperForPropertyPath (nestedPath);
! }
! else
! {
! return this;
! }
! }
! /// <summary>
! /// Find a custom <see cref="System.ComponentModel.TypeConverter"/> for the
! /// given <see cref="System.Type"/> and property.</summary>
! /// <param name="requiredType">
! /// The <see cref="System.Type"/> of the property, can be null if a property
! /// is given but should be specified in any case for consistency checking.
! /// </param>
! /// <param name="propertyPath">
! /// The path of the property (name or nested path), or null if looking for a
! /// <see cref="System.ComponentModel.TypeConverter"/> for all properties of
! /// the given <see cref="System.Type"/>.
! /// </param>
! /// <returns>
! /// The registered <see cref="System.ComponentModel.TypeConverter"/>, or null
! /// if none.
! /// </returns>
public TypeConverter FindCustomConverter (
Type requiredType, string propertyPath)
***************
*** 262,266 ****
}
! private TypeConverter DoFindCustomConverter
(Type requiredType, string propertyName)
{
if (_customConverters == null)
{
return null;
}
if (propertyName != null)
{
// check property-specific type converter first
try
{
TypeConverter editor
= (TypeConverter) _customConverters [propertyName];
if (editor == null)
{
//TODO check for usage with arrays.
int keyIndex = propertyName.IndexOf ('[');
if (keyIndex != - 1)
{
editor = (TypeConverter) _customConverters [
propertyName.Substring (0, keyIndex - 0)];
}
}
if (editor != null)
{
return editor;
}
else
{
if (requiredType == null)
{
// try property type
requiredType = GetPropertyInfo (propertyName).PropertyType;
}
}
}
catch (ObjectsException)
{
// probably an indexed or mapped property
// we need to retrieve the value to determine the type
requiredType = GetPropertyInfo (propertyName).PropertyType;
}
}
return (TypeConverter) _customConverters [requiredType];
}
/// <summary>
--- 369,418 ----
}
! private TypeConverter DoFindCustomConverter
! (Type requiredType, string propertyName)
! {
! if (_customConverters == null)
! {
! return null;
! }
! if (propertyName != null)
! {
! // check property-specific type converter first
! try
! {
! TypeConverter editor
! = (TypeConverter) _customConverters [propertyName];
! if (editor == null)
! {
! //TODO check for usage with arrays.
! int keyIndex = propertyName.IndexOf ('[');
! if (keyIndex != - 1)
! {
! editor = (TypeConverter) _customConverters [
! propertyName.Substring (0, keyIndex - 0)];
! }
! }
! if (editor != null)
! {
! return editor;
! }
! else
! {
! if (requiredType == null)
! {
! // try property type
! requiredType = GetPropertyInfo (propertyName).PropertyType;
! }
! }
! }
! catch (ObjectsException)
! {
! // probably an indexed or mapped property
! // we need to retrieve the value to determine the type
! requiredType = GetPropertyInfo (propertyName).PropertyType;
! }
! }
! return (TypeConverter) _customConverters [requiredType];
! }
/// <summary>
***************
*** 373,379 ****
}
! /// <summary>
/// Retrieve an <see cref="Spring.Objects.ObjectWrapper"/> for the given nested property.
/// </summary>
/// <remarks>
/// <p>
/// Create a new one if not found in the cache.
/// </p>
/// <p>
/// Note: Caching nested <see cref="Spring.Objects.ObjectWrapper"/>s is necessary now,
/// to keep registered custom editors for nested properties.
/// </p>
/// </remarks>
/// <param name="nestedProperty">
/// The property to create the <see cref="Spring.Objects.ObjectWrapper"/> for.
/// </param>
/// <returns>
/// The <see cref="Spring.Objects.ObjectWrapper"/> instance, either cached or newly created.
/// </returns>
private ObjectWrapper GetNestedObjectWrapper (string nestedProperty)
{
if (_nestedObjectWrappers == null)
{
_nestedObjectWrappers = new Hashtable ();
}
// get value of object property
string [] tokens = GetPropertyNameTokens (nestedProperty);
object propertyValue = GetPropertyValue (tokens [0], tokens [1], tokens [2]);
string canonicalName = tokens [0];
if (propertyValue == null)
{
throw new NullValueInNestedPathException (WrappedType, canonicalName);
}
// lookup cached sub-ObjectWrapper, create new one if not found
ObjectWrapper nestedOw = (ObjectWrapper) _nestedObjectWrappers [canonicalName];
if (nestedOw == null)
{
//logger.debug("Creating new nested BeanWrapper for property '" + canonicalName + "'");
nestedOw = new ObjectWrapper (propertyValue, _nestedPath + canonicalName + NestedPropertySeparator);
// inherit all type-specific TypeConverters
if (_customConverters != null)
{
ICollection types = _customConverters.Keys;
foreach (Type requiredType in types)
{
TypeConverter typeConverter = (TypeConverter)_customConverters[requiredType];
nestedOw.RegisterCustomConverter(requiredType, null, typeConverter);
}
}
_nestedObjectWrappers[canonicalName] = nestedOw;
}
else
{
#region Instrumentation
if (log.IsDebugEnabled)
! {
log.Debug (
"Using cached nested ObjectWrapper for property '" +
canonicalName + "'");
}
#endregion
}
return nestedOw;
}
! private string [] GetPropertyNameTokens (string propertyName)
{
string actualName = propertyName;
string key = null;
int keyStart = propertyName.IndexOf ('[');
if (keyStart != - 1
&& propertyName.EndsWith ("]"))
{
actualName = propertyName.Substring (0, keyStart - 0);
key = propertyName.Substring(keyStart + 1, (propertyName.Length - 1) - (keyStart + 1));
if (key.StartsWith ("'") && key.EndsWith ("'"))
{
key = key.Substring (1, (key.Length - 1) - (1));
}
else if (key.StartsWith ("\"") && key.EndsWith("\""))
{
key = key.Substring (1, (key.Length - 1) - (1));
}
}
string canonicalName = actualName;
if (key != null)
{
canonicalName += ("[" + key + "]");
}
return new string [] {canonicalName, actualName, key};
}
/// <summary>Get the value of a property.</summary>
--- 525,624 ----
}
! /// <summary>
! /// Retrieve an <see cref="Spring.Objects.ObjectWrapper"/> for the given nested property.
! /// </summary>
! /// <remarks>
! /// <p>
! /// Create a new one if not found in the cache.
! /// </p>
! /// <p>
! /// Note: Caching nested <see cref="Spring.Objects.ObjectWrapper"/>s is necessary now,
! /// to keep registered custom editors for nested properties.
! /// </p>
! /// </remarks>
! /// <param name="nestedProperty">
! /// The property to create the <see cref="Spring.Objects.ObjectWrapper"/> for.
! /// </param>
! /// <returns>
! /// The <see cref="Spring.Objects.ObjectWrapper"/> instance, either cached or newly created.
! /// </returns>
! private ObjectWrapper GetNestedObjectWrapper (string nestedProperty)
! {
! if (_nestedObjectWrappers == null)
! {
! _nestedObjectWrappers = new Hashtable ();
! }
! // get value of object property
! string [] tokens = GetPropertyNameTokens (nestedProperty);
! object propertyValue = GetPropertyValue (tokens [0], tokens [1], tokens [2]);
! string canonicalName = tokens [0];
! if (propertyValue == null)
! {
! throw new NullValueInNestedPathException (WrappedType, canonicalName);
! }
! // lookup cached sub-ObjectWrapper, create new one if not found
! ObjectWrapper nestedOw = (ObjectWrapper) _nestedObjectWrappers [canonicalName];
! if (nestedOw == null)
! {
! #region Instrumentation
! if (log.IsDebugEnabled)
! {
! log.Debug ("Creating new nested ObjectWrapper for property '" + canonicalName + "'.");
! }
! #endregion
!
! nestedOw = new ObjectWrapper (propertyValue, _nestedPath + canonicalName + NestedPropertySeparator);
! // inherit all type-specific TypeConverters
! if (_customConverters != null)
! {
! ICollection types = _customConverters.Keys;
! foreach (Type requiredType in types)
! {
! TypeConverter typeConverter = (TypeConverter)_customConverters[requiredType];
! nestedOw.RegisterCustomConverter(requiredType, null, typeConverter);
! }
! }
! _nestedObjectWrappers[canonicalName] = nestedOw;
! }
! else
! {
! #region Instrumentation
! if (log.IsDebugEnabled)
! {
! log.Debug (
! "Using cached nested ObjectWrapper for property '" +
! canonicalName + "'");
! }
! #endregion
! }
! return nestedOw;
! }
!
! private string [] GetPropertyNameTokens (string propertyName)
! {
! string actualName = propertyName;
! string key = null;
! int keyStart = propertyName.IndexOf ('[');
! if (keyStart != - 1
! && propertyName.EndsWith ("]"))
! {
! actualName = propertyName.Substring (0, keyStart - 0);
! key = propertyName.Substring(keyStart + 1, (propertyName.Length - 1) - (keyStart + 1));
! if (key.StartsWith ("'") && key.EndsWith ("'"))
! {
! key = key.Substring (1, (key.Length - 1) - (1));
! }
! else if (key.StartsWith ("\"") && key.EndsWith("\""))
! {
! key = key.Substring (1, (key.Length - 1) - (1));
! }
! }
! string canonicalName = actualName;
! if (key != null)
! {
! canonicalName += ("[" + key + "]");
! }
! return new string [] {canonicalName, actualName, key};
! }
/// <summary>Get the value of a property.</summary>
***************
*** 383,387 ****
/// <returns>The value of the property.</returns>
/// <exception cref="Spring.Objects.FatalObjectException">
! /// If there is no such property, if the property isn&t readable, or
/// if getting the property value throws an exception.
/// </exception>
--- 628,632 ----
/// <returns>The value of the property.</returns>
/// <exception cref="Spring.Objects.FatalObjectException">
! /// If there is no such property, if the property isn't readable, or
/// if getting the property value throws an exception.
/// </exception>
***************
*** 441,449 ****
! /// <summary>
/// Look for a default <see cref="System.ComponentModel.TypeConverter"/>
/// to handle common cases.
/// </summary>
/// <param name="requiredType">
/// The <see cref="System.Type"/> that is registered to be converted.
/// </param>
/// <returns>
/// The default <see cref="System.ComponentModel.TypeConverter"/> for the
/// supplied <see cref="System.Type"/>.
/// </returns>
! public virtual TypeConverter FindDefaultConverter(Type requiredType)
{
return (TypeConverter) _defaultConverters [requiredType];
--- 686,701 ----
! /// <summary>
! /// Look for a default <see cref="System.ComponentModel.TypeConverter"/>
! /// to handle common cases.
! /// </summary>
! /// <param name="requiredType">
! /// The <see cref="System.Type"/> that is registered to be converted.
! /// </param>
! /// <returns>
/// The default <see cref="System.ComponentModel.TypeConverter"/> for the
/// supplied <see cref="System.Type"/>.
/// </returns>
! public virtual TypeConverter FindDefaultConverter (Type requiredType)
{
return (TypeConverter) _defaultConverters [requiredType];
***************
*** 452,483 ****
/// <summary>
! /// Convert the value to the required type (if necessary from a string).
/// </summary>
! /// <param name="newValue">proposed change value</param>
! /// <param name="requiredType">type we must convert to</param>
! /// <exception cref="Spring.Objects.ObjectsException">if there is an internal error</exception>
! /// <returns>new value, possibly the result of type convertion</returns>
! public virtual object DoTypeConversionIfNecessary(object newValue, Type requiredType)
{
! return DoTypeConversionIfNecessary(null, null, null, newValue, requiredType);
}
! /// <summary>
/// Convert the value to the required <see cref="System.Type"/> (if necessary
/// from a <see cref="System.String"/>), for the specified property.
/// </summary>
/// <param name="propertyName">The name of the property.</param>
/// <param name="fullPropertyName">
/// Legacy, not used. Will refactor out later.
/// </param>
/// <param name="oldValue">
/// The previous value, if available (may be null).
/// </param>
/// <param name="newValue">The proposed change value.</param>
/// <param name="requiredType">
/// The <see cref="System.Type"/> we are trying to convert to.
/// </param>
/// <returns>
/// The new value, possibly the result of type conversion.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If there is an internal error.
/// </exception>
protected internal virtual object DoTypeConversionIfNecessary (
string propertyName, string fullPropertyName, object oldValue,
object newValue, Type requiredType)
{
if (newValue != null)
{
! if (requiredType != null && requiredType.IsArray)
{
// convert individual elements to array elements
Type componentType = requiredType.GetElementType ();
if (newValue is IList)
{
IList list = (IList) newValue;
Array result = Array.CreateInstance (componentType, list.Count);
for (int i = 0; i < list.Count; ++i)
{
//TODO look into this.
//PropertyInfo pi2 = list[i].GetType().GetProperty("Item");
object val = DoTypeConversionIfNecessary(propertyName, propertyName + "[" + i + "]", null, list[i], componentType);
result.SetValue (val, i);
}
return result;
}
//TODO arrays are treated as IList.....
else if (newValue is object [])
{
object [] array = (object []) newValue;
object result = Array.CreateInstance (componentType, array.Length);
for (int i = 0; i < array.Length; ++i)
{
//TODO look into this
//object value_Renamed = DoTypeConversionIfNecessary(propertyName, propertyName + "[" + i + "]", (object) null, array[i], componentType);
// ((Array) result).SetValue(value_Renamed, i);
}
return result;
}
}
TypeConverter typeConverter
= FindCustomConverter (requiredType, fullPropertyName);
// value not of required type?
! if (typeConverter != null
|| requiredType != null
&& !requiredType.IsAssignableFrom (newValue.GetType ()) )
{
if (newValue is string [])
{
newValue = StringUtils.ArrayToCommaDelimitedString ((string []) newValue);
}
if (newValue is string)
{
if (typeConverter == null)
{
//no custom type converter found -> check ObjectWrappers default editors
typeConverter = FindDefaultConverter (requiredType);
if (typeConverter == null)
{
// mmm... is there a TypeConverter for System.Type from a string?
if (requiredType.FullName == typeof (Type).FullName &&
! newValue is string)
! {
// TODO: if newValue references a type from a third party
// assembly, the original version returns null, so
// changed to use ObjectUtils instead. Is this right??
//return Type.GetType (newValue as string);
return ObjectUtils.LocateType(newValue as string);
}
! else
! {
//get standard converter
typeConverter = TypeDescriptor.GetConverter (requiredType);
}
}
}
if (typeConverter != null)
{
try
{
return typeConverter.ConvertFrom (newValue);
}
catch (Exception ex)
{
throw new TypeMismatchException (
CreatePropertyChangeEventArgs (
fullPropertyName, oldValue, newValue),
requiredType, ex);
}
}
else
{
throw new TypeMismatchException (
CreatePropertyChangeEventArgs (
fullPropertyName, oldValue, newValue),
requiredType);
}
}
else if (typeConverter != null)
{
try
{
//return typeConverter.ConvertTo(newValue, requiredType);
return typeConverter.ConvertFrom (newValue);
}
catch (Exception ex)
{
throw new TypeMismatchException (
CreatePropertyChangeEventArgs (
fullPropertyName, oldValue, newValue),
requiredType, ex);
}
}
}
! if (requiredType != null
&& requiredType.IsArray
&& !newValue.GetType ().IsArray)
{
Type componentType = requiredType.GetElementType ();
Array result = Array.CreateInstance (componentType, 1);
object val = DoTypeConversionIfNecessary (propertyName, propertyName + "[0]", null, newValue, componentType);
result.SetValue (val, 0);
return result;
}
}
return newValue;
}
! /// <summary>
/// Utility method to create a property change eve...
[truncated message content] |