333 lines
9.1 KiB
C#
333 lines
9.1 KiB
C#
/***************************************************************************
|
|
* Copyright Andy Brummer 2004-2005
|
|
*
|
|
* This code is provided "as is", with absolutely no warranty expressed
|
|
* or implied. Any use is at your own risk.
|
|
*
|
|
* This code may be used in compiled form in any way you desire. This
|
|
* file may be redistributed unmodified by any means provided it is
|
|
* not sold for profit without the authors written consent, and
|
|
* providing that this notice and the authors name is included. If
|
|
* the source code in this file is used in any commercial application
|
|
* then a simple email would be nice.
|
|
*
|
|
**************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace UtilidadesCSharp.Schedule
|
|
{
|
|
/// <summary>
|
|
/// IParameterSetter represents a serialized parameter list. This is used to provide a partial specialized
|
|
/// method call. This is useful for remote invocation of method calls. For example if you have a method with
|
|
/// 3 parameters. The first 2 might represent static data such as a report and a storage location. The third
|
|
/// might be the time that the report is invoked, which is only known when the method is invoked. Using this,
|
|
/// you just pass the method and the first 2 parameters to a timer object, which supplies the 3rd parameter.
|
|
/// Without these objects, you would have to generate a custom object type for each method you wished to
|
|
/// execute in this manner and store the static parameters as instance variables.
|
|
/// </summary>
|
|
public interface IParameterSetter
|
|
{
|
|
/// <summary>
|
|
/// This resets the setter to the beginning. It is used for setters that rely on positional state
|
|
/// information. It is called prior to setting any method values.
|
|
/// </summary>
|
|
void reset();
|
|
/// <summary>
|
|
/// This method is used to both query support for setting a parameter and actually set the value.
|
|
/// True is returned if the parameter passed in is updated.
|
|
/// </summary>
|
|
/// <param name="pi">The reflection information about this parameter.</param>
|
|
/// <param name="ParameterLoc">The location of the prameter in the parameter list.</param>
|
|
/// <param name="parameter">The parameter object</param>
|
|
/// <returns>true if the parameter is matched and false otherwise</returns>
|
|
bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter);
|
|
}
|
|
|
|
/// <summary>
|
|
/// This setter object takes a simple object array full of parameter data. It applys the objects in order
|
|
/// to the method parameter list.
|
|
/// </summary>
|
|
public class OrderParameterSetter : IParameterSetter
|
|
{
|
|
public OrderParameterSetter(params object[] _Params)
|
|
{
|
|
_ParamList = _Params;
|
|
}
|
|
public void reset()
|
|
{
|
|
_counter = 0;
|
|
}
|
|
public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
|
|
{
|
|
if (_counter >= _ParamList.Length)
|
|
return false;
|
|
parameter = _ParamList[_counter++];
|
|
return true;
|
|
}
|
|
|
|
object[] _ParamList;
|
|
int _counter;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This setter object stores the parameter data in a Hashtable and uses the hashtable keys to match
|
|
/// the parameter names of the method to the parameter data. This allows methods to be called like
|
|
/// stored procedures, with the parameters being passed in independent of order.
|
|
/// </summary>
|
|
public class NamedParameterSetter : IParameterSetter
|
|
{
|
|
public NamedParameterSetter(Hashtable Params)
|
|
{
|
|
_Params = Params;
|
|
}
|
|
public void reset()
|
|
{
|
|
}
|
|
public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
|
|
{
|
|
string ParamName = pi.Name;
|
|
if (!_Params.ContainsKey(ParamName))
|
|
return false;
|
|
parameter = _Params[ParamName];
|
|
return true;
|
|
}
|
|
Hashtable _Params;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// ParameterSetterList maintains a collection of IParameterSetter objects and applies them in order to each
|
|
/// parameter of the method. Each time a match occurs the next parameter is tried starting with the first
|
|
/// setter object until it is matched.
|
|
/// </summary>
|
|
public class ParameterSetterList
|
|
{
|
|
public void Add(IParameterSetter setter)
|
|
{
|
|
_List.Add(setter);
|
|
}
|
|
|
|
public IParameterSetter[] ToArray()
|
|
{
|
|
return (IParameterSetter[])_List.ToArray(typeof(IParameterSetter));
|
|
}
|
|
|
|
public void reset()
|
|
{
|
|
foreach(IParameterSetter Setter in _List)
|
|
Setter.reset();
|
|
}
|
|
|
|
public object[] GetParameters(MethodInfo Method)
|
|
{
|
|
ParameterInfo[] Params = Method.GetParameters();
|
|
object[] Values = new object[Params.Length];
|
|
//TODO: Update to iterate backwards
|
|
for(int i=0; i<Params.Length; ++i)
|
|
SetValue(Params[i], i, ref Values[i]);
|
|
|
|
return Values;
|
|
}
|
|
|
|
public object[] GetParameters(MethodInfo Method, IParameterSetter LastSetter)
|
|
{
|
|
ParameterInfo[] Params = Method.GetParameters();
|
|
object[] Values = new object[Params.Length];
|
|
//TODO: Update to iterate backwards
|
|
for(int i=0; i<Params.Length; ++i)
|
|
{
|
|
if (!SetValue(Params[i], i, ref Values[i]))
|
|
LastSetter.GetParameterValue(Params[i], i, ref Values[i]);
|
|
}
|
|
return Values;
|
|
}
|
|
|
|
bool SetValue(ParameterInfo Info, int i, ref object Value)
|
|
{
|
|
foreach(IParameterSetter Setter in _List)
|
|
{
|
|
if (Setter.GetParameterValue(Info, i, ref Value))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ArrayList _List = new ArrayList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// IMethodCall represents a partially specified parameter data list and a method. This allows methods to be
|
|
/// dynamically late invoked for things like timers and other event driven frameworks.
|
|
/// </summary>
|
|
public interface IMethodCall
|
|
{
|
|
ParameterSetterList ParamList { get; }
|
|
object Execute();
|
|
object Execute(IParameterSetter Params);
|
|
void EventHandler(object obj, EventArgs e);
|
|
IAsyncResult BeginExecute(AsyncCallback callback, object obj);
|
|
IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj);
|
|
}
|
|
|
|
delegate object Exec();
|
|
delegate object Exec2(IParameterSetter Params);
|
|
|
|
/// <summary>
|
|
/// Method call captures the data required to do a defered method call.
|
|
/// </summary>
|
|
public class DelegateMethodCall : MethodCallBase, IMethodCall
|
|
{
|
|
public DelegateMethodCall(Delegate f)
|
|
{
|
|
_f = f;
|
|
}
|
|
|
|
public DelegateMethodCall(Delegate f, params object[] Params)
|
|
{
|
|
if (f.Method.GetParameters().Length < Params.Length)
|
|
throw new ArgumentException("Too many parameters specified for delegate", "f");
|
|
|
|
_f = f;
|
|
ParamList.Add(new OrderParameterSetter(Params));
|
|
}
|
|
|
|
public DelegateMethodCall(Delegate f, IParameterSetter Params)
|
|
{
|
|
_f = f;
|
|
ParamList.Add(Params);
|
|
}
|
|
|
|
Delegate _f;
|
|
|
|
public Delegate f
|
|
{
|
|
get { return _f; }
|
|
set { _f = value; }
|
|
}
|
|
|
|
public MethodInfo Method
|
|
{
|
|
get { return _f.Method; }
|
|
}
|
|
|
|
public object Execute()
|
|
{
|
|
return f.DynamicInvoke(GetParameterList(Method));
|
|
}
|
|
|
|
public object Execute(IParameterSetter Params)
|
|
{
|
|
return f.DynamicInvoke(GetParameterList(Method, Params));
|
|
}
|
|
|
|
public void EventHandler(object obj, EventArgs e)
|
|
{
|
|
Execute();
|
|
}
|
|
|
|
Exec _exec;
|
|
public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
|
|
{
|
|
_exec = new Exec(Execute);
|
|
return _exec.BeginInvoke(callback, obj);
|
|
}
|
|
|
|
public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
|
|
{
|
|
Exec2 exec = new Exec2(Execute);
|
|
return exec.BeginInvoke(Params, callback, obj);
|
|
}
|
|
}
|
|
|
|
public class DynamicMethodCall : MethodCallBase, IMethodCall
|
|
{
|
|
public DynamicMethodCall(MethodInfo method)
|
|
{
|
|
_obj = null;
|
|
_method = method;
|
|
}
|
|
|
|
public DynamicMethodCall(object obj, MethodInfo method)
|
|
{
|
|
_obj = obj;
|
|
_method = method;
|
|
}
|
|
|
|
public DynamicMethodCall(object obj, MethodInfo method, IParameterSetter setter)
|
|
{
|
|
_obj = obj;
|
|
_method = method;
|
|
ParamList.Add(setter);
|
|
}
|
|
|
|
object _obj;
|
|
MethodInfo _method;
|
|
|
|
public MethodInfo Method
|
|
{
|
|
get { return _method; }
|
|
set { _method = value; }
|
|
}
|
|
|
|
public object Execute()
|
|
{
|
|
return _method.Invoke(_obj, GetParameterList(Method));
|
|
}
|
|
|
|
public object Execute(IParameterSetter Params)
|
|
{
|
|
return _method.Invoke(_obj, GetParameterList(Method, Params));
|
|
}
|
|
|
|
public void EventHandler(object obj, EventArgs e)
|
|
{
|
|
Execute();
|
|
}
|
|
|
|
Exec _exec;
|
|
public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
|
|
{
|
|
_exec = new Exec(Execute);
|
|
return _exec.BeginInvoke(callback, null);
|
|
}
|
|
|
|
public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
|
|
{
|
|
Exec2 exec = new Exec2(Execute);
|
|
return exec.BeginInvoke(Params, callback, null);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This is a base class that handles the Parameter list management for the 2 dynamic method call methods.
|
|
/// </summary>
|
|
public class MethodCallBase
|
|
{
|
|
ParameterSetterList _ParamList = new ParameterSetterList();
|
|
|
|
public ParameterSetterList ParamList
|
|
{
|
|
get { return _ParamList; }
|
|
}
|
|
|
|
protected object[] GetParameterList(MethodInfo Method)
|
|
{
|
|
ParamList.reset();
|
|
object[] Params = ParamList.GetParameters(Method);
|
|
return Params;
|
|
}
|
|
|
|
protected object[] GetParameterList(MethodInfo Method, IParameterSetter Params)
|
|
{
|
|
ParamList.reset();
|
|
object[] objParams = ParamList.GetParameters(Method, Params);
|
|
return objParams;
|
|
}
|
|
}
|
|
|
|
}
|