Thread: [Adapdev-commits] Adapdev/src/Adapdev/Reflection ClassAccessor.cs,NONE,1.1 ClassAccessorCache.cs,NON
Status: Beta
Brought to you by:
intesar66
From: Sean M. <int...@us...> - 2005-05-25 05:17:59
|
Update of /cvsroot/adapdev/Adapdev/src/Adapdev/Reflection In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10621/src/Adapdev/Reflection Added Files: ClassAccessor.cs ClassAccessorCache.cs FieldAccessor.cs FieldAccessorException.cs IValueAccessor.cs PropertyAccessor.cs PropertyAccessorException.cs Log Message: MIgrated reusable Perseus components Added SmartTreeView Added new caching framework Several Sql fixes Added business rule validation classes Added FieldAccessor for IL generation --- NEW FILE: ClassAccessorCache.cs --- using System; using System.Collections; using System.Text; namespace Adapdev.Reflection { /// <summary> /// Summary description for ClassAccessorCache. /// </summary> public class ClassAccessorCache { private static Hashtable _classes = new Hashtable(); private ClassAccessorCache() { } public static ClassAccessor Get(Type t) { ClassAccessor c = null; if(!_classes.ContainsKey(t.FullName)) { c = new ClassAccessor(t); Add(c); c.LoadAllProperties(); } else { c = _classes[t.FullName] as ClassAccessor; } return c; } public static ClassAccessor Get(object o) { return Get(o.GetType()); } public static void Add(ClassAccessor c) { _classes[c.Type.FullName] = c; } public static void Remove(Type t) { _classes.Remove(t.FullName); } public static void Clear() { _classes.Clear(); } public static int Count { get{return _classes.Count;} } public static string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("Properties for ClassAccessorCache: " + Environment.NewLine); foreach(ClassAccessor c in _classes.Values) { sb.Append(c + Environment.NewLine); } return sb.ToString(); } } } --- NEW FILE: ClassAccessor.cs --- using System; using System.Collections; using System.Reflection; using System.Text; namespace Adapdev.Reflection { /// <summary> /// Summary description for ClassAccessor. /// </summary> public class ClassAccessor { private Type _type = null; private Hashtable _properties = new Hashtable(); private DateTime _created; public ClassAccessor(Type t) { this._type = t; this._created = DateTime.Now; } public ClassAccessor(object o) : this(o.GetType()){} public void AddProperty(string name) { PropertyAccessor accessor = new PropertyAccessor(this._type, name); this._properties[name] = accessor; } public object GetPropertyValue(object o, string propertyName) { this.CheckForAccessor(propertyName); PropertyAccessor accessor = this._properties[propertyName] as PropertyAccessor; return accessor.Get(o); } public PropertyAccessor GetPropertyAccessor(string propertyName) { return this._properties[propertyName] as PropertyAccessor; } public Hashtable GetPropertyAccessors() { return this._properties; } public Type PropertyType(string propertyName) { this.CheckForAccessor(propertyName); PropertyAccessor accessor = this._properties[propertyName] as PropertyAccessor; return accessor.PropertyType; } public Type Type { get { return this._type; } } public void SetPropertyValue(object o, string propertyName, object val) { this.CheckForAccessor(propertyName); PropertyAccessor accessor = this._properties[propertyName] as PropertyAccessor; accessor.Set(o, val); } private void CheckForAccessor(string propertyName) { if(!this.IsPropertyDefined(propertyName)) this.AddProperty(propertyName); } private bool IsPropertyDefined(string propertyName) { return this._properties.ContainsKey(propertyName); } public void LoadAllProperties() { PropertyInfo[] infoArray = this._type.GetProperties(); foreach(PropertyInfo p in infoArray) { this.AddProperty(p.Name); } } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("[" + this._type.FullName + "] Properties loaded: " + Environment.NewLine); foreach(string key in this._properties.Keys) { sb.Append(key + Environment.NewLine); } return sb.ToString(); } public int PropertyCount { get{return this._properties.Count;} } } } --- NEW FILE: FieldAccessor.cs --- // // Author: James Nies // Date: 3/22/2005 // Description: The PropertyAccessor class provides fast dynamic access // to a property of a specified target class. // // *** This code was written by James Nies and has been provided to you, *** // *** free of charge, for your use. I assume no responsibility for any *** // *** undesired events resulting from the use of this code or the *** // *** information that has been provided with it . *** // using System; using System.Reflection; using System.Reflection.Emit; using System.Threading; using System.Collections; namespace Adapdev.Reflection { /// <summary> /// The PropertyAccessor class provides fast dynamic access /// to a property of a specified target class. /// </summary> public class FieldAccessor : IValueAccessor { /// <summary> /// Creates a new property accessor. /// </summary> /// <param name="targetType">Target object type.</param> /// <param name="field">Property name.</param> public FieldAccessor(Type targetType, string field) { this.mTargetType = targetType; this.mField = field; FieldInfo fieldInfo = targetType.GetField(field, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); // // Make sure the property exists // if(fieldInfo == null) { throw new FieldAccessorException( string.Format("Field \"{0}\" does not exist for type " + "{1}.", field, targetType)); } else { this.mCanRead = true; this.mCanWrite = true; //!fieldInfo.IsInitOnly; this.mFieldType = fieldInfo.FieldType; this.fi = fieldInfo; } } /// <summary> /// Gets the property value from the specified target. /// </summary> /// <param name="target">Target object.</param> /// <returns>Property value.</returns> public object Get(object target) { if(mCanRead) { if(this.mEmittedValueAccessor == null) { this.Init(); } return this.mEmittedValueAccessor.Get(target); } else { throw new FieldAccessorException( string.Format("Field \"{0}\" does not have a get method.", mField)); } } /// <summary> /// Sets the property for the specified target. /// </summary> /// <param name="target">Target object.</param> /// <param name="value">Value to set.</param> public void Set(object target, object value) { if(mCanWrite) { if(this.mEmittedValueAccessor == null) { this.Init(); } // // Set the property value // this.mEmittedValueAccessor.Set(target, value); } else { throw new FieldAccessorException( string.Format("Field \"{0}\" does not have a set method.", mField)); } } /// <summary> /// Whether or not the Property supports read access. /// </summary> public bool CanRead { get { return this.mCanRead; } } /// <summary> /// Whether or not the Property supports write access. /// </summary> public bool CanWrite { get { return this.mCanWrite; } } /// <summary> /// The Type of object this property accessor was /// created for. /// </summary> public Type TargetType { get { return this.mTargetType; } } /// <summary> /// The Type of the Property being accessed. /// </summary> public Type FieldType { get { return this.mFieldType; } } private Type mTargetType; private string mField; private Type mFieldType; private IValueAccessor mEmittedValueAccessor; private Hashtable mTypeHash; private bool mCanRead; private bool mCanWrite; private FieldInfo fi; /// <summary> /// This method generates creates a new assembly containing /// the Type that will provide dynamic access. /// </summary> private void Init() { this.InitTypes(); // Create the assembly and an instance of the // property accessor class. Assembly assembly = EmitAssembly(); mEmittedValueAccessor = assembly.CreateInstance("Field") as IValueAccessor; if(mEmittedValueAccessor == null) { throw new Exception("Unable to create property accessor."); } } /// <summary> /// Thanks to Ben Ratzlaff for this snippet of code /// http://www.codeproject.com/cs/miscctrl/CustomPropGrid.asp /// /// "Initialize a private hashtable with type-opCode pairs /// so i dont have to write a long if/else statement when outputting msil" /// </summary> private void InitTypes() { mTypeHash=new Hashtable(); mTypeHash[typeof(sbyte)]=OpCodes.Ldind_I1; mTypeHash[typeof(byte)]=OpCodes.Ldind_U1; mTypeHash[typeof(char)]=OpCodes.Ldind_U2; mTypeHash[typeof(short)]=OpCodes.Ldind_I2; mTypeHash[typeof(ushort)]=OpCodes.Ldind_U2; mTypeHash[typeof(int)]=OpCodes.Ldind_I4; mTypeHash[typeof(uint)]=OpCodes.Ldind_U4; mTypeHash[typeof(long)]=OpCodes.Ldind_I8; mTypeHash[typeof(ulong)]=OpCodes.Ldind_I8; mTypeHash[typeof(bool)]=OpCodes.Ldind_I1; mTypeHash[typeof(double)]=OpCodes.Ldind_R8; mTypeHash[typeof(float)]=OpCodes.Ldind_R4; } /// <summary> /// Create an assembly that will provide the get and set methods. /// </summary> private Assembly EmitAssembly() { // // Create an assembly name // AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "FieldAccessorAssembly"; // // Create a new assembly with one module // AssemblyBuilder newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder newModule = newAssembly.DefineDynamicModule("Module"); // // Define a public class named "Property" in the assembly. // TypeBuilder myType = newModule.DefineType("Field", TypeAttributes.Public); // // Mark the class as implementing IPropertyAccessor. // myType.AddInterfaceImplementation(typeof(IValueAccessor)); // Add a constructor ConstructorBuilder constructor = myType.DefineDefaultConstructor(MethodAttributes.Public); // // Define a method for the get operation. // Type[] getParamTypes = new Type[] {typeof(object)}; Type getReturnType = typeof(object); MethodBuilder getMethod = myType.DefineMethod("Get", MethodAttributes.Public | MethodAttributes.Virtual, getReturnType, getParamTypes); // // From the method, get an ILGenerator. This is used to // emit the IL that we want. // ILGenerator getIL = getMethod.GetILGenerator(); // // Emit the IL. // // MethodInfo targetGetMethod = this.mTargetType.GetMethod("get_" + this.mField); // // if(targetGetMethod != null) // { // TODO: Fix this piece getIL.DeclareLocal(typeof(object)); getIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object) getIL.Emit(OpCodes.Castclass, this.mTargetType); //Cast to the source type getIL.Emit(OpCodes.Stfld, this.mField); //getIL.EmitCall(OpCodes.Call, targetGetMethod, null); //Get the property value // if(targetGetMethod.ReturnType.IsValueType) // { // getIL.Emit(OpCodes.Box, targetGetMethod.ReturnType); //Box if necessary // } getIL.Emit(OpCodes.Stloc_0); //Store it getIL.Emit(OpCodes.Ldloc_0); // } // else // { // getIL.ThrowException(typeof(MissingMethodException)); // } getIL.Emit(OpCodes.Ret); // // Define a method for the set operation. // Type[] setParamTypes = new Type[] {typeof(object), typeof(object)}; Type setReturnType = null; MethodBuilder setMethod = myType.DefineMethod("Set", MethodAttributes.Public | MethodAttributes.Virtual, setReturnType, setParamTypes); // // From the method, get an ILGenerator. This is used to // emit the IL that we want. // ILGenerator setIL = setMethod.GetILGenerator(); // // Emit the IL. // MethodInfo targetSetMethod = this.mTargetType.GetMethod("set_" + this.mField); if(targetSetMethod != null) { Type paramType = targetSetMethod.GetParameters()[0].ParameterType; setIL.DeclareLocal(paramType); setIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object) setIL.Emit(OpCodes.Castclass, this.mTargetType); //Cast to the source type setIL.Emit(OpCodes.Ldarg_2); //Load the second argument //(value object) if(paramType.IsValueType) { setIL.Emit(OpCodes.Unbox, paramType); //Unbox it if(mTypeHash[paramType]!=null) //and load { OpCode load = (OpCode)mTypeHash[paramType]; setIL.Emit(load); } else { setIL.Emit(OpCodes.Ldobj,paramType); } } else { setIL.Emit(OpCodes.Castclass, paramType); //Cast class } setIL.EmitCall(OpCodes.Callvirt, targetSetMethod, null); //Set the property value } else { setIL.ThrowException(typeof(MissingMethodException)); } setIL.Emit(OpCodes.Ret); // // Load the type // myType.CreateType(); return newAssembly; } } } --- NEW FILE: PropertyAccessor.cs --- // // Author: James Nies // Date: 3/22/2005 // Description: The PropertyAccessor class provides fast dynamic access // to a property of a specified target class. // // *** This code was written by James Nies and has been provided to you, *** // *** free of charge, for your use. I assume no responsibility for any *** // *** undesired events resulting from the use of this code or the *** // *** information that has been provided with it . *** // using System; using System.Reflection; using System.Reflection.Emit; using System.Threading; using System.Collections; namespace Adapdev.Reflection { /// <summary> /// The PropertyAccessor class provides fast dynamic access /// to a property of a specified target class. /// </summary> public class PropertyAccessor : IValueAccessor { /// <summary> /// Creates a new property accessor. /// </summary> /// <param name="targetType">Target object type.</param> /// <param name="property">Property name.</param> public PropertyAccessor(Type targetType, string property) { this.mTargetType = targetType; this.mProperty = property; PropertyInfo propertyInfo = targetType.GetProperty(property); // // Make sure the property exists // if(propertyInfo == null) { throw new PropertyAccessorException( string.Format("Property \"{0}\" does not exist for type " + "{1}.", property, targetType)); } else { this.mCanRead = propertyInfo.CanRead; this.mCanWrite = propertyInfo.CanWrite; this.mPropertyType = propertyInfo.PropertyType; } } /// <summary> /// Gets the property value from the specified target. /// </summary> /// <param name="target">Target object.</param> /// <returns>Property value.</returns> public object Get(object target) { if(mCanRead) { if(this.mEmittedValueAccessor == null) { this.Init(); } return this.mEmittedValueAccessor.Get(target); } else { throw new PropertyAccessorException( string.Format("Property \"{0}\" does not have a get method.", mProperty)); } } /// <summary> /// Sets the property for the specified target. /// </summary> /// <param name="target">Target object.</param> /// <param name="value">Value to set.</param> public void Set(object target, object value) { if(mCanWrite) { if(this.mEmittedValueAccessor == null) { this.Init(); } // // Set the property value // this.mEmittedValueAccessor.Set(target, value); } else { throw new PropertyAccessorException( string.Format("Property \"{0}\" does not have a set method.", mProperty)); } } /// <summary> /// Whether or not the Property supports read access. /// </summary> public bool CanRead { get { return this.mCanRead; } } /// <summary> /// Whether or not the Property supports write access. /// </summary> public bool CanWrite { get { return this.mCanWrite; } } /// <summary> /// The Type of object this property accessor was /// created for. /// </summary> public Type TargetType { get { return this.mTargetType; } } /// <summary> /// The Type of the Property being accessed. /// </summary> public Type PropertyType { get { return this.mPropertyType; } } private Type mTargetType; private string mProperty; private Type mPropertyType; private IValueAccessor mEmittedValueAccessor; private Hashtable mTypeHash; private bool mCanRead; private bool mCanWrite; /// <summary> /// This method generates creates a new assembly containing /// the Type that will provide dynamic access. /// </summary> private void Init() { this.InitTypes(); // Create the assembly and an instance of the // property accessor class. Assembly assembly = EmitAssembly(); mEmittedValueAccessor = assembly.CreateInstance("Property") as IValueAccessor; if(mEmittedValueAccessor == null) { throw new Exception("Unable to create property accessor."); } } /// <summary> /// Thanks to Ben Ratzlaff for this snippet of code /// http://www.codeproject.com/cs/miscctrl/CustomPropGrid.asp /// /// "Initialize a private hashtable with type-opCode pairs /// so i dont have to write a long if/else statement when outputting msil" /// </summary> private void InitTypes() { mTypeHash=new Hashtable(); mTypeHash[typeof(sbyte)]=OpCodes.Ldind_I1; mTypeHash[typeof(byte)]=OpCodes.Ldind_U1; mTypeHash[typeof(char)]=OpCodes.Ldind_U2; mTypeHash[typeof(short)]=OpCodes.Ldind_I2; mTypeHash[typeof(ushort)]=OpCodes.Ldind_U2; mTypeHash[typeof(int)]=OpCodes.Ldind_I4; mTypeHash[typeof(uint)]=OpCodes.Ldind_U4; mTypeHash[typeof(long)]=OpCodes.Ldind_I8; mTypeHash[typeof(ulong)]=OpCodes.Ldind_I8; mTypeHash[typeof(bool)]=OpCodes.Ldind_I1; mTypeHash[typeof(double)]=OpCodes.Ldind_R8; mTypeHash[typeof(float)]=OpCodes.Ldind_R4; } /// <summary> /// Create an assembly that will provide the get and set methods. /// </summary> private Assembly EmitAssembly() { // // Create an assembly name // AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "PropertyAccessorAssembly"; // // Create a new assembly with one module // AssemblyBuilder newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder newModule = newAssembly.DefineDynamicModule("Module"); // // Define a public class named "Property" in the assembly. // TypeBuilder myType = newModule.DefineType("Property", TypeAttributes.Public); // // Mark the class as implementing IPropertyAccessor. // myType.AddInterfaceImplementation(typeof(IValueAccessor)); // Add a constructor ConstructorBuilder constructor = myType.DefineDefaultConstructor(MethodAttributes.Public); // // Define a method for the get operation. // Type[] getParamTypes = new Type[] {typeof(object)}; Type getReturnType = typeof(object); MethodBuilder getMethod = myType.DefineMethod("Get", MethodAttributes.Public | MethodAttributes.Virtual, getReturnType, getParamTypes); // // From the method, get an ILGenerator. This is used to // emit the IL that we want. // ILGenerator getIL = getMethod.GetILGenerator(); // // Emit the IL. // MethodInfo targetGetMethod = this.mTargetType.GetMethod("get_" + this.mProperty); if(targetGetMethod != null) { getIL.DeclareLocal(typeof(object)); getIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object) getIL.Emit(OpCodes.Castclass, this.mTargetType); //Cast to the source type getIL.EmitCall(OpCodes.Call, targetGetMethod, null); //Get the property value if(targetGetMethod.ReturnType.IsValueType) { getIL.Emit(OpCodes.Box, targetGetMethod.ReturnType); //Box if necessary } getIL.Emit(OpCodes.Stloc_0); //Store it getIL.Emit(OpCodes.Ldloc_0); } else { getIL.ThrowException(typeof(MissingMethodException)); } getIL.Emit(OpCodes.Ret); // // Define a method for the set operation. // Type[] setParamTypes = new Type[] {typeof(object), typeof(object)}; Type setReturnType = null; MethodBuilder setMethod = myType.DefineMethod("Set", MethodAttributes.Public | MethodAttributes.Virtual, setReturnType, setParamTypes); // // From the method, get an ILGenerator. This is used to // emit the IL that we want. // ILGenerator setIL = setMethod.GetILGenerator(); // // Emit the IL. // MethodInfo targetSetMethod = this.mTargetType.GetMethod("set_" + this.mProperty); if(targetSetMethod != null) { Type paramType = targetSetMethod.GetParameters()[0].ParameterType; setIL.DeclareLocal(paramType); setIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object) setIL.Emit(OpCodes.Castclass, this.mTargetType); //Cast to the source type setIL.Emit(OpCodes.Ldarg_2); //Load the second argument //(value object) if(paramType.IsValueType) { setIL.Emit(OpCodes.Unbox, paramType); //Unbox it if(mTypeHash[paramType]!=null) //and load { OpCode load = (OpCode)mTypeHash[paramType]; setIL.Emit(load); } else { setIL.Emit(OpCodes.Ldobj,paramType); } } else { setIL.Emit(OpCodes.Castclass, paramType); //Cast class } setIL.EmitCall(OpCodes.Callvirt, targetSetMethod, null); //Set the property value } else { setIL.ThrowException(typeof(MissingMethodException)); } setIL.Emit(OpCodes.Ret); // // Load the type // myType.CreateType(); return newAssembly; } } } --- NEW FILE: IValueAccessor.cs --- // // Author: James Nies // Date: 3/22/2005 // Description: The PropertyAccessor class uses this interface // for creating a type at runtime for accessing an individual // property on a target object. // // *** This code was written by James Nies and has been provided to you, *** // *** free of charge, for your use. I assume no responsibility for any *** // *** undesired events resulting from the use of this code or the *** // *** information that has been provided with it . *** // using System; namespace Adapdev.Reflection { /// <summary> /// The IPropertyAccessor interface defines a property /// accessor. /// </summary> public interface IValueAccessor { /// <summary> /// Gets the value stored in the property for /// the specified target. /// </summary> /// <param name="target">Object to retrieve /// the property from.</param> /// <returns>Property value.</returns> object Get(object target); /// <summary> /// Sets the value for the property of /// the specified target. /// </summary> /// <param name="target">Object to set the /// property on.</param> /// <param name="value">Property value.</param> void Set(object target, object value); } } --- NEW FILE: PropertyAccessorException.cs --- // // Author: James Nies // Date: 3/22/2005 // Description: Exception that can be thrown from the PropertyAccessor // class. // // *** This code was written by James Nies and has been provided to you, *** // *** free of charge, for your use. I assume no responsibility for any *** // *** undesired events resulting from the use of this code or the *** // *** information that has been provided with it . *** // using System; namespace Adapdev.Reflection { /// <summary> /// PropertyAccessorException class. /// </summary> public class PropertyAccessorException : Exception { public PropertyAccessorException(string message) : base(message) { } } } --- NEW FILE: FieldAccessorException.cs --- using System; namespace Adapdev.Reflection { /// <summary> /// PropertyAccessorException class. /// </summary> public class FieldAccessorException : Exception { public FieldAccessorException(string message) : base(message) { } } } |