250 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Reflection;
 | |
| using System.Text;
 | |
| using Csla.Properties;
 | |
| 
 | |
| namespace Csla
 | |
| {
 | |
|   internal static class MethodCaller
 | |
|   {
 | |
|     const BindingFlags allLevelFlags =
 | |
|       BindingFlags.FlattenHierarchy |
 | |
|       BindingFlags.Instance |
 | |
|       BindingFlags.Public |
 | |
|       BindingFlags.NonPublic;
 | |
| 
 | |
|     const BindingFlags oneLevelFlags =
 | |
|       BindingFlags.DeclaredOnly |
 | |
|       BindingFlags.Instance |
 | |
|       BindingFlags.Public |
 | |
|       BindingFlags.NonPublic;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Gets a reference to the DataPortal_Create method for
 | |
|     /// the specified business object type.
 | |
|     /// </summary>
 | |
|     /// <param name="objectType">Type of the business object.</param>
 | |
|     /// <param name="criteria">Criteria parameter value.</param>
 | |
|     /// <remarks>
 | |
|     /// If the criteria parameter value is an integer, that is a special
 | |
|     /// flag indicating that the parameter should be considered missing
 | |
|     /// (not Nothing/null - just not there).
 | |
|     /// </remarks>
 | |
|     public static MethodInfo GetCreateMethod(Type objectType, object criteria)
 | |
|     {
 | |
|       MethodInfo method = null;
 | |
|       if (criteria is int)
 | |
|       {
 | |
|         // an "Integer" criteria is a special flag indicating
 | |
|         // that criteria is empty and should not be used
 | |
|         method = MethodCaller.GetMethod(objectType, "DataPortal_Create");
 | |
|       }
 | |
|       else
 | |
|         method = MethodCaller.GetMethod(objectType, "DataPortal_Create", criteria);
 | |
|       return method;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Gets a reference to the DataPortal_Fetch method for
 | |
|     /// the specified business object type.
 | |
|     /// </summary>
 | |
|     /// <param name="objectType">Type of the business object.</param>
 | |
|     /// <param name="criteria">Criteria parameter value.</param>
 | |
|     /// <remarks>
 | |
|     /// If the criteria parameter value is an integer, that is a special
 | |
|     /// flag indicating that the parameter should be considered missing
 | |
|     /// (not Nothing/null - just not there).
 | |
|     /// </remarks>
 | |
|     public static MethodInfo GetFetchMethod(Type objectType, object criteria)
 | |
|     {
 | |
|       MethodInfo method = null;
 | |
|       if (criteria is int)
 | |
|       {
 | |
|         // an "Integer" criteria is a special flag indicating
 | |
|         // that criteria is empty and should not be used
 | |
|         method = MethodCaller.GetMethod(objectType, "DataPortal_Fetch");
 | |
|       }
 | |
|       else
 | |
|         method = MethodCaller.GetMethod(objectType, "DataPortal_Fetch", criteria);
 | |
|       return method;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Uses reflection to dynamically invoke a method
 | |
|     /// if that method is implemented on the target object.
 | |
|     /// </summary>
 | |
|     public static object CallMethodIfImplemented(
 | |
|       object obj, string method, params object[] parameters)
 | |
|     {
 | |
|       MethodInfo info = GetMethod(obj.GetType(), method, parameters);
 | |
|       if (info != null)
 | |
|         return CallMethod(obj, info, parameters);
 | |
|       else
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Uses reflection to dynamically invoke a method,
 | |
|     /// throwing an exception if it is not
 | |
|     /// implemented on the target object.
 | |
|     /// </summary>
 | |
|     public static object CallMethod(
 | |
|       object obj, string method, params object[] parameters)
 | |
|     {
 | |
|       MethodInfo info = GetMethod(obj.GetType(), method, parameters);
 | |
|       if (info == null)
 | |
|         throw new NotImplementedException(
 | |
|           method + " " + Resources.MethodNotImplemented);
 | |
|       return CallMethod(obj, info, parameters);
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Uses reflection to dynamically invoke a method,
 | |
|     /// throwing an exception if it is not
 | |
|     /// implemented on the target object.
 | |
|     /// </summary>
 | |
|     public static object CallMethod(
 | |
|       object obj, MethodInfo info, params object[] parameters)
 | |
|     {
 | |
|       // call a private method on the object
 | |
|       object result;
 | |
|       try
 | |
|       {
 | |
|         result = info.Invoke(obj, parameters);
 | |
|       }
 | |
|       catch (Exception e)
 | |
|       {
 | |
|         throw new Csla.Server.CallMethodException(
 | |
|           info.Name + " " + Resources.MethodCallFailed, e.InnerException);
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Uses reflection to locate a matching method
 | |
|     /// on the target object.
 | |
|     /// </summary>
 | |
|     public static MethodInfo GetMethod(
 | |
|       Type objectType, string method, params object[] parameters)
 | |
|     {
 | |
|       MethodInfo result = null;
 | |
| 
 | |
|       // try to find a strongly typed match
 | |
|       // put all param types into a list of Type
 | |
|       List<Type> types = new List<Type>();
 | |
|       foreach (object item in parameters)
 | |
|       {
 | |
|         if (item == null)
 | |
|           types.Add(typeof(object));
 | |
|         else
 | |
|           types.Add(item.GetType());
 | |
|       }
 | |
| 
 | |
|       // first see if there's a matching method
 | |
|       // where all params match types
 | |
|       result = FindMethod(objectType, method, types.ToArray());
 | |
| 
 | |
|       if (result == null)
 | |
|       {
 | |
|         // no match found - so look for any method
 | |
|         // with the right number of parameters
 | |
|         result = FindMethod(objectType, method, parameters.Length);
 | |
|       }
 | |
| 
 | |
|       // no strongly typed match found, get default
 | |
|       if (result == null)
 | |
|       {
 | |
|         try
 | |
|         { 
 | |
|           result = objectType.GetMethod(method, allLevelFlags); 
 | |
|         }
 | |
|         catch (AmbiguousMatchException)
 | |
|         {
 | |
|           MethodInfo[] methods = objectType.GetMethods();
 | |
|           foreach (MethodInfo m in methods)
 | |
|             if (m.Name == method && m.GetParameters().Length == parameters.Length)
 | |
|             {
 | |
|               result = m;
 | |
|               break;
 | |
|             }
 | |
|           if (result == null)
 | |
|             throw;
 | |
|         }
 | |
|       }
 | |
|       return result;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Returns a business object type based on
 | |
|     /// the supplied criteria object.
 | |
|     /// </summary>
 | |
|     public static Type GetObjectType(object criteria)
 | |
|     {
 | |
|       if (criteria.GetType().IsSubclassOf(typeof(CriteriaBase)))
 | |
|       {
 | |
|         // get the type of the actual business object
 | |
|         // from CriteriaBase 
 | |
|         return ((CriteriaBase)criteria).ObjectType;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         // get the type of the actual business object
 | |
|         // based on the nested class scheme in the book
 | |
|         return criteria.GetType().DeclaringType;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Returns information about the specified
 | |
|     /// method, even if the parameter types are
 | |
|     /// generic and are located in an abstract
 | |
|     /// generic base class.
 | |
|     /// </summary>
 | |
|     public static MethodInfo FindMethod(Type objType, string method, Type[] types)
 | |
|     {
 | |
|       MethodInfo info = null;
 | |
|       do
 | |
|       {
 | |
|         //find for a strongly typed match
 | |
|         info = objType.GetMethod(method, oneLevelFlags, null, types, null);
 | |
|         if (info != null)
 | |
|           break;  //match found
 | |
| 
 | |
|         objType = objType.BaseType;
 | |
|       } while (objType != null);
 | |
| 
 | |
|       return info;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Returns information about the specified
 | |
|     /// method, finding the method based purely
 | |
|     /// on the method name and number of parameters.
 | |
|     /// </summary>
 | |
|     public static MethodInfo FindMethod(Type objType, string method, int parameterCount)
 | |
|     {
 | |
|       // walk up the inheritance hierarchy looking
 | |
|       // for a method with the right number of
 | |
|       // parameters
 | |
|       MethodInfo result = null;
 | |
|       Type currentType = objType;
 | |
|       do
 | |
|       {
 | |
|         MethodInfo info = currentType.GetMethod(method, oneLevelFlags);
 | |
|         if (info != null)
 | |
|         {
 | |
|           if (info.GetParameters().Length == parameterCount)
 | |
|           {
 | |
|             // got a match so use it
 | |
|             result = info;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         currentType = currentType.BaseType;
 | |
|       } while (currentType != null);
 | |
|       return result;
 | |
|     }
 | |
|   }
 | |
| }
 |