Хорошо, сначала объясню правила:
Мне нужна функция, которая создает делегат, соответствующий любому типу делегата, который инкапсулирует тело, которое вызывает делегат типа (Object) (Object [] args) с 'args ', содержащий все аргументы, переданные исходному делегату во время вызова.
Моя работа на данный момент:
delegate void TestDelegate(int x, int y);
delegate object TestDelegate2(object[] args);
static void Main(string[] sargs)
{
TestDelegate d = (TestDelegate)CreateAnonymousFromType(typeof(TestDelegate));
object ret = d.DynamicInvoke(2, 6);
if (ret != null) { Console.WriteLine(ret); }
Console.ReadKey();
}
static void SpecialInvoke(int x, int y)
{
Console.WriteLine("x: {0}\r\ny: {1}", x, y);
}
static Delegate CreateAnonymousFromType(Type type)
{
MethodInfo method = type.GetMethod("Invoke");
TestDelegate2 _delegate = new TestDelegate2(
delegate(object[] args)
{
Console.WriteLine("x: {0}\r\ny: {1}", args[0], args[1]);
return "This is the return";
});
var typeargs = CreateArgs(method.GetParameters());
var argindex = -1;
var tmp = Expression.Parameter(typeof(Object), "tmp");
var index = Expression.Parameter(typeof(int), "index");
var length = Expression.Constant(typeargs.Length);
var _break = Expression.Label("breakto");
var delegateargs = Expression.Parameter(typeof(object[]), "args");
return Expression.Lambda(
type,
Expression.Block(
new[] { tmp, index, delegateargs },
Expression.Assign(index, Expression.Constant(0)),
Expression.Assign(delegateargs, Expression.NewArrayBounds(typeof(Object), length)),
Expression.Loop(
Expression.IfThenElse(Expression.LessThan(index, length),
Expression.Block(
Expression.Assign(tmp, Expression.Convert(typeargs[++argindex], typeof(Object))),
Expression.Assign(Expression.ArrayAccess(delegateargs, index), tmp),
Expression.PostIncrementAssign(index)
),
Expression.Break(_break)
),
_break
),
Expression.Call(_delegate.Method, delegateargs)
),
typeargs
).Compile();
}
static ParameterExpression[] CreateArgs(ParameterInfo[] _params)
{
ParameterExpression[] ret = new ParameterExpression[_params.Length];
for (int i = 0; i < ret.Length; i++)
ret[i] = Expression.Parameter(_params[i].ParameterType, _params[i].Name);
return ret;
}
Теперь этот SORTA работает ... Я получаю только значение typeargs [0] передан делегату «TestDelegate2» для обоих параметров x и y, параметр «args» во время выполнения - это object [] {2, 2}, и я не могу найти способ увеличить значение «argindex»внутри контекста итерации аргумента ... количество параметров во время компиляции неопределенно.Кто-нибудь знает, как я могу решить эту проблему?
Я пытался просто скопировать массив аргументов, используя Expression.NewArrayInit (typeof (Object), typeargs), но это не удается сказать, что он не может использовать Int32 для инициализации массиваObject
Я также пробовал это: var arguments = Expression.Constant (typeargs);
И получая доступ к значению "arguments" в "index", однако при этом получаются строки "x"и" y ".. очевидно имена аргументов, а не их значения.
Это, честно говоря, моя первая крупная попытка использования деревьев выражений, поэтому любая помощь ... неважно, как мало.Будет оценено.
Спасибо.