2017-01-18 3 views
1

다음과 같이 내가 쓴 확장은 다음과 같습니다C#에서 동적으로 생성 유형에 대한 일반적인 확장 메서드를 호출하는 방법을

public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, bool> predicate) where T : class, new() 
{ 
    .... 
} 

동적 반사하는 TypeBuilder를 사용하여 생성하면 다음과 같은 화면이 나타납니다 클래스 샘플.

public class Sample 
{ 
    public Sample() 
    { 
     Children= new ObservableTestCollection<Sample>(this); 
    } 

    public Sample(IEnumerable<Sample> source) 
    { 
     Children= new ObservableTestCollection<Sample>(this, source); 
    } 

    public ObservableTestCollection<Sample> Children; 
} 

ObservableTestCollection 위 여기 아래에 반사하는 TypeBuilder가 내장되어 ObservableCollection에

하는 TypeBuilder하여 산출 : 목적은 내가 시간을 실행 만든 인스턴스화 은 같다. 내가하고 싶은 무엇 입니다 : 여기

var type = typeBuilder.CreateType(); 
var obj = Activator.CreateInstance(type); 
var results = (IEnumerable<...>)(obj.GetProperty("Children").GetValue(obj)).Traverse(s=>s!=null); 

문제는 샘플의 종류가 반사하는 TypeBuilder에 의해 생성 된 하나이기 때문에 내가 IEnumerable을 캐스팅 할 수 없다는 것입니다. 즉, 코드에서 Sample에 대한 명확한 유형이 없음을 의미합니다.

그래서 일반 유형 IEnumerable<...>을 전송하거나 Traverse의 확장 메소드를 호출하는 방법을 찾고 싶습니다.

미리 감사드립니다.

+2

무엇이 질문입니까? – qxg

답변

2

귀하의 ObservableTestCollection<T> 유형 IEnumerable<T>을 구현하거나 구현이이 같은 확장 방법을 사용할 수 있도록하는 것이이 유형에서 파생한다 :

:

public class ObservableTestCollection<T> : IEnumerable<T> 
{ 
    private Sample sample; 
    private IEnumerable<Sample> source; 

    public ObservableTestCollection(Sample sample) 
    { 
     this.sample = sample; 
    } 

    public ObservableTestCollection(Sample sample, IEnumerable<Sample> source) 
    { 
     this.sample = sample; 
     this.source = source; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 
} 

그런 다음이처럼에 반영 할 수

var obj = Activator.CreateInstance(typeof(Sample)); 
var pi = obj.GetType().GetProperty("Children"); 
var ct = Convert.ChangeType(obj, pi.PropertyType) as ObservableTestCollection<Sample>; 
var results = (IEnumerable <Sample>)(ct as IEnumerable<object>).Traverse(s => s.Equals("1")); 

나는 에 object을 사용하고 있지만 필요한 것은 무엇이든 사용할 수 있습니다. 또한 런타임에 Children 속성에 항목을 추가해야 확장 기능을 사용하여 항목을 트래버스 할 수 있지만이를 알고 있다고 가정합니다.

EDIT 당신은 귀하의 질문에 편집이 추가 :

여기에서의 문제는 샘플의 종류가 반사하는 TypeBuilder에 의해 생성 된 하나이기 때문에 내가 IEnumerable을 캐스팅 할 수 없다는 것입니다. 즉, 코드에서 Sample에 대한 명확한 유형이 없음을 의미합니다.

상관 없지만 여전히 작동합니다. 여기에 Sample을 수업으로 언급하지 않고 비행 중에 작성한 코드로 보겠습니다.

AssemblyName assemblyName 
= new AssemblyName("MyDynamicAssembly"); 
AssemblyBuilder assemblyBuilder 
    = AppDomain.CurrentDomain.DefineDynamicAssembly(
     assemblyName, 
     AssemblyBuilderAccess.Run); 
ModuleBuilder moduleBuilder 
    = assemblyBuilder.DefineDynamicModule("MyDynamicModule"); 
TypeBuilder typeBuilder 
    = moduleBuilder.DefineType("Sample"); 
var obj = Activator.CreateInstance(typeBuilder.CreateType()); 
var pi = obj.GetType().GetProperty("Children"); 
var ct = Convert.ChangeType(obj, pi.PropertyType) as IEnumerable<object>; 
var results = (ct as IEnumerable<object>).Traverse(s => s.Equals("1")); 
+0

나는 내가 지금 직면하고있는 문제에 대해 더 잘 표현하기 위해 쓴 질문에 약간의 업데이트를했다. 좀 더 자세하게 살펴볼 수 있겠습니까? 감사합니다 –

+0

고마워요 @ 코딩 요시. 나는 약간의 변경을 var ct = Convert.ChangeType (s.GetProperty ("Children"). GetValue (s), pi.PropertyType) IEnumerable 으로 변경했다. –