From: Michael D. <mik...@us...> - 2004-08-22 06:19:04
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Property In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30320/NHibernate/Property Added Files: BasicGetter.cs BasicPropertyAccessor.cs BasicSetter.cs FieldAccessor.cs FieldGetter.cs FieldMUnderscorePrefixAccessor.cs FieldSetter.cs FieldUnderscorePrefixAccessor.cs IGetter.cs IPropertyAccessor.cs ISetter.cs PropertyAccessorFactory.cs Log Message: Classes need to make direct write to fields possible. --- NEW FILE: BasicPropertyAccessor.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// Accesses property values via a get/set pair, which may be nonpublic. /// The default (and recommended strategy). /// </summary> public class BasicPropertyAccessor : IPropertyAccessor { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(BasicPropertyAccessor)); #region IPropertyAccessor Members public ISetter GetSetter(System.Type type, string propertyName) { BasicSetter result = GetSetterOrNull(type, propertyName); if (result==null) throw new PropertyNotFoundException( "Could not find a setter for property " + propertyName + " in class " + type.FullName ); return result; } public IGetter GetGetter(System.Type theClass, string propertyName) { BasicGetter result = GetGetterOrNull(theClass, propertyName); if (result == null) throw new PropertyNotFoundException( "Could not find a setter for property " + propertyName + " in class " + theClass.FullName ); return result; } #endregion private static BasicSetter GetSetterOrNull(System.Type type, string propertyName) { if (type == typeof(object) || type == null) return null; //PropertyInfo property = type.GetProperty(propertyName); PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.DeclaredOnly); if (property != null) { return new BasicSetter(type, property, propertyName); } else { BasicSetter setter = GetSetterOrNull( type.BaseType, propertyName ); if (setter == null) { System.Type[] interfaces = type.GetInterfaces(); for ( int i=0; setter==null && i<interfaces.Length; i++) { setter = GetSetterOrNull(interfaces[i], propertyName); } } return setter; } } private static BasicGetter GetGetterOrNull(System.Type type, string propertyName) { if (type==typeof(object) || type==null) return null; //PropertyInfo property = type.GetProperty(propertyName); PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.DeclaredOnly); if (property != null) { return new BasicGetter(type, property, propertyName); } else { BasicGetter getter = GetGetterOrNull( type.BaseType, propertyName ); if (getter == null) { System.Type[] interfaces = type.GetInterfaces(); for (int i=0; getter==null && i<interfaces.Length; i++) { getter = GetGetterOrNull( interfaces[i], propertyName ); } } return getter; } } } } --- NEW FILE: FieldGetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { public sealed class FieldGetter : IGetter { private readonly FieldInfo field; private readonly System.Type clazz; private readonly string name; public FieldGetter(FieldInfo field, System.Type clazz, string name) { this.field = field; this.clazz = clazz; this.name = name; } #region IGetter Members public object Get(object target) { try { return field.GetValue(target); } catch(Exception e) { throw new PropertyAccessException( e, "could not get a field value by reflection", false, clazz, name ); } } public System.Type ReturnType { get { return field.ReflectedType; } } public string PropertyName { get { return null; } } public PropertyInfo Property { get { return null; } } #endregion } } --- NEW FILE: IGetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// Gets values of a particular property /// </summary> public interface IGetter { /// <summary> /// Get the property value from the given instance /// </summary> /// <param name="target"></param> /// <returns></returns> object Get(object target); /// <summary> /// Get the declared Type. /// </summary> /// <returns></returns> System.Type ReturnType{ get; } /// <summary> /// Optional operation (return null) /// </summary> /// <returns></returns> string PropertyName { get; } /// <summary> /// Optional operation (return null) /// </summary> /// <returns></returns> /// <remarks> /// This is used to tell the Proxy which getter to intercept as the <id> /// property. /// </remarks> PropertyInfo Property { get; } } } --- NEW FILE: FieldUnderscorePrefixAccessor.cs --- using System; namespace NHibernate.Property { /// <summary> /// Access fields directly. /// </summary> /// <remarks> /// This accesses fields with the following naming convention: /// Property Name = "Id" /// Field Name = "_id" /// </remarks> public class FieldUnderscorePrefixAccessor : FieldAccessor { /// <summary> /// Converts the Property's name into a Field name with the /// "_" prefixing the Property's name converted to camel style /// casing. /// </summary> /// <param name="propertyName">The name of the Property.</param> /// <returns>The name of the Field.</returns> /// <remarks> /// This uses the convention that a Property <c>Id</c> will have a field </c>_id</c> /// </remarks> protected override string GetFieldName(string propertyName) { return "_" + base.GetFieldName(propertyName) ; } } } --- NEW FILE: BasicGetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// /// </summary> public sealed class BasicGetter : IGetter { private System.Type clazz; private PropertyInfo property; private string propertyName; public BasicGetter(System.Type clazz, PropertyInfo property, string propertyName) { this.clazz = clazz; this.property = property; this.propertyName = propertyName; } #region IGetter Members public object Get(object target) { try { return property.GetValue(target, new object[0]); } catch (Exception e) { throw new PropertyAccessException(e, "Exception occurred", false, clazz, propertyName); } } public System.Type ReturnType { get { return property.PropertyType; } } public string PropertyName { get { return property.Name; } } public PropertyInfo Property { get{ return property; } } #endregion } } --- NEW FILE: IPropertyAccessor.cs --- using System; namespace NHibernate.Property { /// <summary> /// Abstracts the notion of a "property". Defines a strategy for accessing the /// value of an attribute. /// </summary> public interface IPropertyAccessor { /// <summary> /// Create a "getter" for the named attribute /// </summary> /// <param name="theClass"></param> /// <param name="propertyName"></param> /// <returns></returns> /// <exception cref="PropertyNotFoundException" > /// </exception> IGetter GetGetter(System.Type theClass, string propertyName); /// <summary> /// Create a "setter" for the named attribute /// </summary> /// <param name="theClass"></param> /// <param name="propertyName"></param> /// <returns></returns> /// <exception cref="PropertyNotFoundException" > /// </exception> ISetter GetSetter(System.Type theClass, string propertyName); } } --- NEW FILE: FieldMUnderscorePrefixAccessor.cs --- using System; namespace NHibernate.Property { /// <summary> /// Access fields directly. /// </summary> /// <remarks> /// This accesses fields with the following naming convention: /// Property Name = "Id" /// Field Name = "m_id" /// </remarks> public class FieldMUnderscorePrefixAccessor : FieldAccessor { /// <summary> /// Converts the Property's name into a Field name with the /// "m_" prefixing the Property's name converted to camel style /// casing. /// </summary> /// <param name="propertyName">The name of the Property.</param> /// <returns>The name of the Field.</returns> /// <remarks> /// This uses the convention that a Property <c>Id</c> will have a field </c>m_id</c> /// </remarks> protected override string GetFieldName(string propertyName) { return "m_" + base.GetFieldName(propertyName) ; } } } --- NEW FILE: PropertyAccessorFactory.cs --- using System; using System.Reflection; using NHibernate.Util; namespace NHibernate.Property { /// <summary> /// Factory for creating the various PropertyAccessor strategies. /// </summary> public class PropertyAccessorFactory { private static readonly IPropertyAccessor basicPropertyAccessor = new BasicPropertyAccessor(); private static readonly IPropertyAccessor fieldAccessor = new FieldAccessor(); private static readonly IPropertyAccessor fieldUnderscoreAccessor = new FieldUnderscorePrefixAccessor(); private static readonly IPropertyAccessor fieldMUnderscoreAccessor = new FieldMUnderscorePrefixAccessor(); private PropertyAccessorFactory() { throw new NotSupportedException("Should not be creating a PropertyAccessorFactory - only use the static methods."); } public static IPropertyAccessor GetPropertyAccessor(string type) { if( type==null || "property".Equals(type) ) return basicPropertyAccessor; switch(type) { case "field" : return fieldAccessor; case "field.underscore" : return fieldUnderscoreAccessor; case "field.munderscore" : return fieldMUnderscoreAccessor; } System.Type accessorClass; try { accessorClass = ReflectHelper.ClassForName(type); } catch(TypeLoadException tle) { throw new MappingException("could not find PropertyAccessor type: " + type, tle); } try { return (IPropertyAccessor) Activator.CreateInstance(accessorClass); } catch(Exception e) { throw new MappingException("could not instantiate PropertyAccessor type: " + type, e ); } } } } --- NEW FILE: FieldSetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { public sealed class FieldSetter : ISetter { private readonly FieldInfo field; private readonly System.Type clazz; private readonly string name; public FieldSetter(FieldInfo field, System.Type clazz, string name) { this.field = field; this.clazz = clazz; this.name = name; } #region ISetter Members public void Set(object target, object value) { try { field.SetValue( target, value ); } catch(Exception e) { throw new PropertyAccessException(e, "could not set a field value by reflection", true, clazz, name); } } public string PropertyName { get { return null; } } public PropertyInfo Property { get { return null; } } #endregion } } --- NEW FILE: ISetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// Summary description for ISetter. /// </summary> public interface ISetter { /// <summary> /// Set the property value from the given instance /// </summary> /// <param name="target"></param> /// <param name="value"></param> /// <exception cref="HibernateException"> /// </exception> void Set(object target, object value); /// <summary> /// Optional operation (return null) /// </summary> /// <returns></returns> string PropertyName { get; } /// <summary> /// Optional operation (return null) /// </summary> /// <returns></returns> /// <remarks> /// This is used to tell the Proxy which setter to intercept as the <id> /// property. /// </remarks> PropertyInfo Property { get; } } } --- NEW FILE: FieldAccessor.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// Access fields directly. /// </summary> /// <remarks> /// This accesses fields with the following naming convention: /// Property Name = "Id" /// Field Name = "id" /// </remarks> public class FieldAccessor : IPropertyAccessor { #region IPropertyAccessor Members public IGetter GetGetter(System.Type theClass, string propertyName) { string fieldName = GetFieldName(propertyName); return new FieldGetter( GetField( theClass, fieldName ), theClass, fieldName ); } public ISetter GetSetter(System.Type theClass, string propertyName) { string fieldName = GetFieldName(propertyName); return new FieldSetter( GetField( theClass, fieldName ), theClass, fieldName ); } #endregion private static FieldInfo GetField(System.Type clazz, string fieldName) { if( clazz==null || clazz==typeof(object) ) { throw new PropertyNotFoundException("field not found: " + fieldName); } FieldInfo field = clazz.GetField( fieldName, BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.DeclaredOnly ); if(field==null) { field = GetField( clazz.BaseType, fieldName ); } // h2.0.3 has a check to see if the field is public - is there a worry about // that in .net?? return field; } /// <summary> /// Converts the Property's name into a Field using camel style casing. /// </summary> /// <param name="propertyName">The name of the Property.</param> /// <returns>The name of the Field.</returns> /// <remarks> /// This uses the convention that a Property named <c>Id</c> will have a field </c>id</c> /// </remarks> protected virtual string GetFieldName(string propertyName) { return propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1); } } } --- NEW FILE: BasicSetter.cs --- using System; using System.Reflection; namespace NHibernate.Property { /// <summary> /// /// </summary> public sealed class BasicSetter : ISetter { private System.Type clazz; private PropertyInfo property; private string propertyName; public BasicSetter(System.Type clazz, PropertyInfo property, string propertyName) { this.clazz = clazz; this.property = property; this.propertyName = propertyName; } #region ISetter Members public void Set(object target, object value) { try { property.SetValue(target, value, new object[0]); } catch (Exception e) { throw new PropertyAccessException(e, "Exception occurred", true, clazz, propertyName); } } public string PropertyName { get { return property.Name; } } public PropertyInfo Property { get { return property; } } #endregion } } |