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;
|
|
}
|
|
}
|
|
}
|