2017-01-03 7 views
0

생성자를 생성하는 것은 쉽지 않습니다.생성자를 생성하는 방법

나는 다음과 같은 코드

public class Sample 
{   

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

그리고 ObservableTestCollection의 소스의 두 번째 생성자를 만들려고 노력하고 있어요 :

public class ObservableTestCollection<T> : ObservableCollection<T> 
{ 
    public T Parent; 
    public ObservableTestCollection(T parent):this(parent, Enumerable.Empty<T>()) 
    {   
    } 
    public ObservableTestCollection(T parent, IEnumerable<T> source): base(source) 
    { 
     Parent = parent; 
    } 
} 

을 다음과 같이 내가 쓴 생성자 빌더는 다음과 같습니다

 //first constructor   
     var obsCtor1 = typeOfCts.GetConstructors().First(c => c.GetParameters().Length == 1); 
     obsCtor1 = TypeBuilder.GetConstructor(genericTypeOfCts, obsCtor1); 
     var constructorParameters = new Type[] { typeBuilder }; 
     var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, constructorParameters); 
     il = ctorBuilder.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_1); 
     il.Emit(OpCodes.Call, setParentMethod); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Newobj, obsCtor1); 
     il.Emit(OpCodes.Call, setChildrenMethod); 
     il.Emit(OpCodes.Ret); 


     //second constructor 
      var obsCtor2 = typeOfCts.GetConstructors().First(c => c.GetParameters().Length == 2); 
     obsCtor2 = TypeBuilder.GetConstructor(genericTypeOfCts, obsCtor2); 
     var ctorParam = typeOfCts.MakeGenericType(typeBuilder);   
     constructorParameters = new Type[] { typeBuilder, ctorParam };   
     ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, constructorParameters); 
     il = ctorBuilder.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_1); 
     il.Emit(OpCodes.Call, setParentMethod); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_2); 
     il.Emit(OpCodes.Newobj, obsCtor2); 
     il.Emit(OpCodes.Call, setChildrenMethod); 
     il.Emit(OpCodes.Ret); 

     Type type = typeBuilder.CreateType(); 
     var obj1 = Activator.CreateInstance(type, new object[] { null }); 
     var obj2 = Activator.CreateInstance(type, obj1); 
     assemblyBuilder.Save(assemblyFileName); 

     var children = (IList)obj2.GetType().GetProperty(selfRefDerivedCollectionName).GetValue(obj2, null); 
     ((INotifyCollectionChanged)children).CollectionChanged += Program_CollectionChanged; 

     var obj3 = Activator.CreateInstance(type, new object[] { null }); 
     children.Add(obj3); 


     var listOf = typeof(List<>); 
     var listOfType = listOf.MakeGenericType(type); 
     var list =(IList) Activator.CreateInstance(listOfType); 
     obj1 = Activator.CreateInstance(type, new object[] { null }); 
     list.Add(obj1); 
     obj1 = Activator.CreateInstance(type, new object[] { null }); 
     list.Add(obj1); 
     var obj4 = Activator.CreateInstance(type, list); 

누군가 내 코드에 무엇이 잘못되었는지 알아낼 수 있습니까?

+0

당신이 당신에게 당신의 C# 예제의 IL을 제공하는 반사 형 도구를 사용 했습니까? – RQDQ

+0

나는 ILDASM과 다른 도구를 아직 사용하지 않았습니다. 어떤 생각을 가지고 있습니까? –

+0

Telerik JustDecompile을 사용합니다. http://www.telerik.com/products/decompiler.aspx하지만 다른 좋은 선택이있을 것입니다. – RQDQ

답변

0

문제점은 두 번째 생성자를 작성하는 것이 아니라 일반 유형의 인스턴스를 작성하는 중임을 발견했습니다. 갱신

I는 다음과 같습니다

 Type type = typeBuilder.CreateType(); 
     var obj1 = Activator.CreateInstance(type, new object[] { null }); 
     var obj2 = Activator.CreateInstance(type, obj1); 
     assemblyBuilder.Save(assemblyFileName); 

     var children = (IList)obj2.GetType().GetProperty(selfRefDerivedCollectionName).GetValue(obj2, null); 
     ((INotifyCollectionChanged)children).CollectionChanged += Program_CollectionChanged; 

     var obj3 = Activator.CreateInstance(type, new object[] { null }); 
     children.Add(obj3); 

     var genericType = typeOfCts.MakeGenericType(type); 


     var list = Activator.CreateInstance(genericType, new object[] { null}); 
     obj1 = Activator.CreateInstance(type, new object[] { null }); 

     list.GetType().GetMethod("Add").Invoke(list, new object[] { obj1 }); 


     obj1 = Activator.CreateInstance(type, new object[] { null }); 
     list.GetType().GetMethod("Add").Invoke(list, new object[] { obj1 }); 

     var obj4 = Activator.CreateInstance(type, new object[] { null, list });