2009-02-04 3 views
2

내 응용 프로그램이 IList를 처리 중입니다. 다른 사용자 정의 유형의 IList입니다. IList에 포함 된 객체의 유형을 확인한 다음 해당 유형의 새 인스턴스를 만든 다음 IList 자체에 추가한다고 생각할 수 있습니다. 동적으로 IList 유형의 새 인스턴스를 만듭니다.

그래서 한 번에 나는
IList<Customer> l; 

를 처리 할 수 ​​있으며 나는

Customer c = new Customer(0, "None") 

고객의 새로운 인스턴스를 생성 한 다음 목록

l.Add(c); 
에 그것을 추가 할

이 작업을 런타임에 동적으로 수행하는 것이 문제의 핵심입니다. 누군가가 나에게 몇 가지 조언을 해줄 수 있기를 바랍니다. 감사합니다 브렌든

+0

당신은 내가 그 C#을 추측하지만 어떤 곳은 .... – Peter

+0

가 그래, 난 그냥 질문 나 자신을 볼 때, 감사 – user48408

답변

4

이 시도 :

public static void AddNewElement<T>(IList<T> l, int i, string s) 
    { 
     T obj = (T)Activator.CreateInstance(typeof(T), new object[] { i, s }); 
     l.Add(obj); 
    } 

사용법 :

IList<Customer> l = new List<Customer>(); 
    l.Add(new Customer(1,"Hi there ...")); 

    AddNewElement(l, 0, "None"); 

(EDIT) :

다음이 시도 :

public static void AddNewElement2(IList l, int i, string s) 
    { 
     if (l == null || l.Count == 0) 
      throw new ArgumentNullException(); 
     object obj = Activator.CreateInstance(l[0].GetType(), new object[] { i, s }); 
     l.Add(obj); 
    } 
+0

이것이 작동 할 것이라고 생각하지만 목록을 처리하는 방식으로 허용되지 않습니다. 즉 foreach (arrayOfPopulatingLists의 IList l) { AddNewElement (l, 0, "None") } // 메소드에 대한 인수를 사용에서 유추 할 수 없습니다. 일반 메서드를 호출해야합니까? – user48408

+0

업데이트 된 답변보기 ... –

+0

감사합니다. Bruno, 완벽하게 작동합니다. – user48408

0

큰 문제는 여기에 있습니다 : 유형을 모르는 경우 어떻게 새 것을 만드는지 알고 있습니까? 세계의 모든 유형이 int와 문자열을 사용하는 생성자를 가진 것은 아닙니다.

0

예 죄송합니다. 처리해야 할 개체 집합에 int 및 문자열을 허용하는 생성자가 있다고 언급 했어야합니다. 당신이 매개 변수가없는 생성자를 사용하고 나중에 속성을 설정할 수 있다면 당신은 당신의 방법은 일반적인 할 수

2

, 같은 : -

MyBase는 INT와 문자열 속성을 노출하여 클래스의 기본은
void Process<T>(IList<T> list, int x, string y) where T : MyBase, new() 
    { 
     T t = new T(); 
     t.X = x; 
     t.Y = y; 
     list.Add(t); 
    } 

. 원하는 경우 기본 클래스가 아닌 인터페이스를 사용할 수 있습니다.

+0

이 코드가 작동하지 않는다는 것을 깨달았다 거기에 있어야 당신의 랭을 명시해야 팁 , 그리고이 효과를 얻기 위해 비슷한 것은 없습니다. –

+0

죄송합니다. 게시물이 적절하게 편집되었습니다. 감사합니다 –

+0

이것은 좋아 보인다. 사용 측면에서. foreach에서 처리중인 IList의 arrayList가 있습니다. 그래서 foreach (arrayOfILists의 IList l) {Process (l, 0, "None"); } 제네릭에 익숙하지 않은 이유는 무엇인지 컴파일하지 않을 이유가 무엇인지 모르겠다. ( – user48408

1

Activator.CreateInstance 메서드를 사용하면 클래스의 생성자를 유형 이름 (문자열) 또는 System.Type의 인스턴스를 통해 호출 할 수 있습니다.

+0

문제는 여기에 그 유형 (들)이 다른 어셈블리에 있기 때문에 Activator.CreateInstance를 호출 할 수 없다고 생각합니다. – user48408

+1

어셈블리가 제대로로드되는 한, 이것은 문제가되지 않습니다. –

+0

감사합니다. Activator.CreateInstance works – user48408

1

을 당신이해야한다고 생각 디자인을 변경하십시오. abstract factory pattern을 사용할 수 있습니다. 리플렉션을 사용하면 성능이 저하됩니다.

다음은 공장 용 코드입니다.

public abstract class MyStore { 
    public abstract string Name { get; } 
    public abstract void AddItem(int id, string name); 
} 

추상 클래스에 코드가없는 경우 인터페이스 사용을 고려해 볼 수 있습니다.

그런 다음 고객 상점을 생성하십시오.

public class CustomerStore : MyStore, IEnumerable<Customer> { 
    List<Customer> list = new List<Customer>(); 

    public override string Name { get { return "Customer Store"; } } 
    public override void AddItem(int id, string name) { 
     list.Add(new Customer(id, name)); 
    } 
    public IEnumerator<Customer> GetEnumerator() { 
     return list.GetEnumerator(); 
    } 
} 

사용

foreach (MyStore store in List<MyStore>) 
    store.AddItem(0, "None"); 

당신은 제네릭 형식은 IList의 형식 인수를 반환

switch (store.Name) { 
case "Customer Store": 
    SomeMethod((CustomerStore)store); 
    break; 
default: 
    throw new WhatEverException(); 
} 
1

당신은 Type.GetGenericArguments 방법을 사용할 수 있습니다 사용, 저장의 유형을 고려할 경우 < T>. 그런 다음 적절한 생성자를 호출하십시오.

Type T = l.GetType ().GetGenericArguments () [ 0 ]; 
    ConstructorInfo ctor = T.GetConstructor (
    new Type [ 2 ] { typeof (int), typeof (string) }); 
    System.Diagnostics.Debug.Assert (ctor != null); 
    object instance = ctor.Invoke (
    new object [ 2 ] { 0, "None" }); 
0

가장 좋은 방법은 IList의 유형은 인덱서의 속성 유형에 보는 것입니다 받으실 수 있습니다!

var collectionType = targetList.GetType().GetProperty("Item").PropertyType; 
var constructor = collectionType.GetConstructor(Type.EmptyTypes); 
var newInstance = constructor.Invoke(null); 
관련 문제