2008-10-24 5 views
9

class<T>과 같은 generics를 사용하는 클래스의 런타임 인스턴스를 만들 필요가 있습니다. 이전에 T 유형을 알지 못했지만 다음과 같이하고 싶습니다.Generics를 동적으로 사용하는 것이 불가능합니까?

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     lists.Add(type, new List<type>()); /* this new List<type>() doesn't work */ 
    } 

    return lists; 
} 

...하지만 할 수 있습니다. '티. C#에서는 일반 대괄호 안에 형식 변수를 쓸 수 없다고 생각합니다. 그것을 할 다른 방법이 있습니까?

+0

런타임시 유형 안전 일반 객체를 생성하려는 이유를 제시 할 수 있습니까? –

+0

필자는 프로토콜 버퍼를 포팅 할 때 특히 여러 번 해 봤습니다. –

+0

내 직업에서 지속성 프레임 워크에 대한 어댑터를 수행하고 있으며 클래스는 작업을 수행하기 위해이 정보가 필요합니다. –

답변

17

당신은 그렇게 할 수 없어 - 제네릭의 포인트는 대부분 컴파일 시간 타입 - 안전 -하지만 당신은 반사와 함께 작업을 수행 할 수 있습니다 얼마나 자주 당신이있어에 따라

public Dictionary<Type, object> GenerateLists(List<Type> types) 
{ 
    Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

    foreach (Type type in types) 
    { 
     Type genericList = typeof(List<>).MakeGenericType(type); 
     lists.Add(type, Activator.CreateInstance(genericList)); 
    } 

    return lists; 
} 
+0

다시 Jon에게 감사드립니다. CreateInstance에 빈 생성자가 필요합니까? 나는 그것을 가지고 있지 않다. 실제로 매개 변수를 입력해야한다. –

+0

생성자가 필요합니다. 생성자를 사용하지 않으려면 System.Runtime.Serialization 어셈블리에서 FormatterServices.GetUninitializedObject()를 사용할 수 있습니다. –

+1

@Victor : Activator.CreateInstance에 매개 변수를 사용하는 오버로드가 있거나 Type.GetConstructor를 사용하여 호출 할 수 있습니다. 기본적으로 형식에서 유형의 인스턴스로 이동하는 방법은 많습니다. 하나를 선택하십시오. –

4

Activator.CreateInstance를 사용하여이 메서드를 호출하면 속도가 느려질 수 있습니다. 또 다른 옵션은 다음과 같이하는 것입니다 :

private dictionary> delegates = new Dictionary>();

public Dictionary<Type, object> GenerateLists(List<Type> types) 
    { 
     Dictionary<Type, object> lists = new Dictionary<Type, object>(); 

     foreach (Type type in types) 
     { 
      if (!delegates.ContainsKey(type)) 
       delegates.Add(type, CreateListDelegate(type)); 
      lists.Add(type, delegates[type]()); 
     } 

     return lists; 
    } 

    private Func<object> CreateListDelegate(Type type) 
    { 
     MethodInfo createListMethod = GetType().GetMethod("CreateList"); 
     MethodInfo genericCreateListMethod = createListMethod.MakeGenericMethod(type); 
     return Delegate.CreateDelegate(typeof(Func<object>), this, genericCreateListMethod) as Func<object>; 
    } 

    public object CreateList<T>() 
    { 
     return new List<T>(); 
    } 

첫 번째 히트에서는 목록을 만드는 일반 메서드에 대한 대리인을 만든 다음 사전에 넣습니다. 이후에 히트 할 때마다 해당 유형의 델리게이트를 호출하게됩니다.

희망이 도움이됩니다.

+0

jonni 감사합니다.이 메서드는 단지 한 번만 호출합니다. 그렇지 않으면 대리자를 유지하는 것이 좋습니다. –

관련 문제