There is nothing impossible in this world... but with some limitations.
I've found one solution, but it’s most strange code I have ever wrote.
The goal is to create a factory, that producing a Delegates with the same signature as the original delegate. Each of producing delegate will invoke a simple action, that convert it's input arguments to object[] and then call method «MyMeth»:
static Delegate MagicFactory(Action<object[]> callingMehod, Type[] ArgsTypes){/**/}
We got a clear solution with this magic factory:
PropertyInfo del = FindDelegate(); //Got an original delegate property
var adel = del.PropertyType; //Got an original deleagate type
var ainvk = adel.GetMethod ("Invoke"); //Got an invoke method of original delegate
var types = ainvk.GetParameters ()
.Select (p => p.ParameterType)
.ToArray (); //delegate arguments types
//Our magic factory:
var delegateHandler = HeavyReflectionTools.MagicFactory(MyMeth, types);
//Converting produced delegate to original delegate type:
var convertedHandler = Delegate.CreateDelegate (adel, delegateHandler, "Invoke");
//Set produced delegate to original property:
del.SetValue (Contract, convertedHandler, null);
But code of this factory is very strange… Please let me know if you’ve got an easier solution.
My solution:
First of all C# got a family of a generic delegate-types "Action" with up to 16 generic parameters. Do you ever seen a method with more than 16 input arguments? i hope no. So Action object with corresponding generic implementation is a good output for this factory.
On other hand C# can produce a different generic types by Activator:
var genericType = typeof(SomeType<>).MakeGenericTypeDefinition(Type[] argTypes);
var myObj = Activator.CreateInstance(genericType) as IMyInterface;
But its nearly-impossible to create action-objects in this way. Instead, I can create a generic Sub factory for each Action generic type. All this sub factories implement non-generic interface:
interface IDelegateSubFactory{
Delegate GetActionConverter (Action<object[]> act);
}
So There will be a 16 sub factories with different generic implementations, one for each corresponding Action generic implementation:
(It is not a code)
class SubFactory<T>: IDelegateSubFactory -> Action<T>
class SubFactoty<T1,T2>: IDelegateSubFactory -> Action<T1,T2>
class SubFactoty<T1,T2,T3>: IDelegateSubFactory -> Action<T1,T2,T3>
/*...*/
class SubFactoty<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>: IDelegateSubFactory -> Action< <T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>
each of these sub factories is very simple:
class SubFactoty <T1,T2,T3>: IDelegateSubFactory{
public Delegate GetActionConverter (Action<object[]> act){
Action<T1,T2,T3> ans = (t1,t2,t3)=> act(new object[]{t1,t2,t3});
return ans;
}
}
class SubFactoty <T1,T2,T3,T4>: IDelegateSubFactory{
public Delegate GetActionConverter (Action<object[]> act){
Action<T1,T2,T3,T4> ans = (t1,t2,t3,t4)=> act(new object[]{t1,t2,t3,t4});
return ans;
}
}
At last I can fill a body of a magic factory:
static Delegate MagicFactory(Action<object[]> action, Type[] types){
Type t = null;
switch (types.Length){
case 0: return new Action(()=>action(new object[0]));
case 1: t = typeof(SubFactory <,>); break;
case 2: t = typeof(SubFactory <,>); break;
case 3: t = typeof(SubFactory <,,>); break;
case 4: t = typeof(SubFactory <,,,>); break;
case 5: t = typeof(SubFactory <,,,,>); break;
/*...*/
case 16: t = typeof(SubFactory <,,,,,,,,,,,,,,,>); break;
default: throw new Exception("Cannot handle a method with more than 16 arguments. Try to use complex object instead");
}
var gt = t.MakeGenericType (types);
var gen = Activator.CreateInstance (gt) as IDelegateSubFactory;
return gen.GetActionConverter (action);
}
And thats Works on C# 3 and CompactFramework too. Without Emit. But the size of SubFactories implementation is about 140 lines.
Same technique is also suitable for delegates that has return-type. In this case you should use a Func type instead of action and correct Factory and SubFactories.
But I still hope to find a simpler solution.