2014-09-25 5 views
0

일부 개체에는 리플렉션을 통해 얻은 여러 개의 호출 인수가있는 대리인 속성이 있습니다. 예를 들어 :대리자 속성을 여러 개의 인수로 연결하고 object [] 유형의 단일 인수를 사용하는 메서드

public Action<int,double,DateTime> myDel{get;set;} 

그래서 내가 그것을

PropertyInfo del = FindDelegate(); 
var adel = del.PropertyType;//Type of Delegate 
var ainvk = adel.GetMethod ("Invoke");//Invoke Method Info 

에 대해만을 반사 정보를 가지고 그리고 난 이런 서명하는 방법이 있습니다

public void MyMeth(object[] args){/*...*/} 

을 나는이 방법을 호출 할 필요가 델리게이트 myDel을 호출 할 때. 문제는 리플렉션을 통해 대리인을 얻었고 숫자와 유형의 입력 인수는 변수입니다.

C# 3에서 EMIT를 사용하지 않고 해결할 수있는 방법이 있습니까? C# 4는 어떻습니까? 감사합니다.

+0

아니요. IL을 방출하지 않으면이 작업을 수행 할 수 없습니다. 컴파일 타임에 델리게이트의 서명을 알지 못하는 한 적어도. 모든 유형의 대리자에 할당 할 수있는 정적 메서드를 만들 수 없습니다. – Servy

답변

0

이 세상에는 불가능한 것이 없지만 몇 가지 제한이 있습니다.

하나의 해결책을 찾았지만 필자가 쓴 가장 이상한 코드입니다.

목표는 원래 위임과 동일한 서명을 가진 대리인을 생성하는 팩터 리를 만드는 것입니다.

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를 수정해야합니다.

하지만 여전히 간단한 솔루션을 찾고 싶습니다.