이 세상에는 불가능한 것이 없지만 몇 가지 제한이 있습니다.
하나의 해결책을 찾았지만 필자가 쓴 가장 이상한 코드입니다.
목표는 원래 위임과 동일한 서명을 가진 대리인을 생성하는 팩터 리를 만드는 것입니다.
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);
:
static Delegate MagicFactory(Action<object[]> callingMehod, Type[] ArgsTypes){/**/}
우리는이 마법 공장 맑은 용액을 가지고 : 생산 위임의 각은 방법«MyMeth»을 [] 오브젝트를 한 후 전화를 입력 인수의 전환이 간단한 조치를 호출합니다
하지만이 공장의 코드는 매우 이상합니다 ... 더 쉬운 해결책이 있다면 알려주세요.
내 솔루션 : 모든 C#의
먼저 최대 16 개 제네릭 매개 변수와 함께 일반 대의원 종류의 "액션"의 가족을 얻었다. 입력 인자가 16 개 이상인 메소드를 본 적이 있습니까? 나는 희망이 없다. 따라서 해당 일반 구현을 사용하는 Action 객체는이 팩토리에 대한 좋은 결과물입니다. 반면 C 번호에
은 액티베이터하여 다른 일반적인 유형을 생성 할 수 있습니다 :
var genericType = typeof(SomeType<>).MakeGenericTypeDefinition(Type[] argTypes);
var myObj = Activator.CreateInstance(genericType) as IMyInterface;
하지만 거의 불가능한 이런 방식으로 액션 객체를 만들 수 있습니다. 대신, 각 Action 제네릭 형식에 대해 일반 Sub 팩터 리를 만들 수 있습니다.이 모든 하위 공장은 제네릭이 아닌 인터페이스를 구현 :
interface IDelegateSubFactory{
Delegate GetActionConverter (Action<object[]> act);
}
그래서 16 개 서브 다른 일반적인 구현과 공장, 각 해당 작업 일반적인 구현을위한 일이있을 것입니다 :
(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>
이 하위 공장의 각 매우 간단합니다 :
: 마침내
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;
}
}
내가 마술 공장의 몸을 채울 수 있습니다
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);
}
그리고 thats C# 3 및 CompactFramework에서도 작동합니다. 방출하지 않고. 그러나 SubFactories 구현의 크기는 약 140 라인입니다.
동일한 기술은 반환 형식이있는 대리자에도 적합합니다. 이 경우 작업 대신 Func 유형을 사용하고 Factory 및 SubFactory를 수정해야합니다.
하지만 여전히 간단한 솔루션을 찾고 싶습니다.
아니요. IL을 방출하지 않으면이 작업을 수행 할 수 없습니다. 컴파일 타임에 델리게이트의 서명을 알지 못하는 한 적어도. 모든 유형의 대리자에 할당 할 수있는 정적 메서드를 만들 수 없습니다. – Servy