2012-04-25 3 views
4

유형 매개 변수에서 일반 클래스를 만드는 방법이 있습니까?유형 매개 변수의 일반 클래스

public class SomeClass 
{ 
    public Type TypeOfAnotherClass { get; set; } 
} 

public class OneMoreClass 
{ 
} 

public class GenericClass<T> 
    where T : class 
{ 
    public void DoNothing() {} 
} 

public class GenericClass 
{ 
    public static GenericClass<T> GetInstance<T>(T ignored) 
     where T : class 
    { 
     return new GenericClass<T>(); 
    } 
} 

내가 원하는 것은 형식에서 GenericClass을 만드는 것입니다 :

나는 이런 식으로 뭔가가있다. 예 : 여기

var SC = new SomeClass(); 
SC.TypeOfAnotherClass = typeof(OneMoreClass); 
var generic = GenericClass.GetInstance(SC.TypeOfAnotherClass); 

Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic.GetType()); 

나는 GenericClass<OneMoreClass>의 인스턴스를 얻을 것으로 예상하지만 나는 또한 해당 유형의 인스턴스를 사용하여 시도 GenericClass<Type>

를 얻을. 예 :

var generic = GenericClass.GetInstance(Activator.CreateInstance(SC.TypeOfAnotherClass)); 

내가

GenericClass<object>를 얻을이 시간이 작업을 수행 할 수있는 방법이 있나요?

답변

7

:

public class GenericClass 
{ 
    public static GenericClass<T> GetInstance<T>(T ignored) 
     where T : class 
    { 
     return new GenericClass<T>(); 
    } 

    public static GenericClass<T> GetInstance<T>() 
     where T : class 
    { 
     return new GenericClass<T>(); 
    } 
} 

목 사용 :

var generic1 = GenericClass.GetInstance<OneMoreClass>(); 
    var generic2 = GenericClass.GetInstance(new OneMoreClass()); 

어설 내가 제대로 이해하면, 이것은 당신이 찾고있는 무슨이다)를 작성하면 사용하면됩니다.

var generic = GenericClass.GetInstance<OneMoreClass>(); 

하지만 빌드 할 때 모를 것이라고 가정하고 런타임시 type을 가져와야합니다. 당신은 반사와 함께 할 수 있지만, 그것은 꽤하지 않고, 천천히 : 당신이 빌드시 결과 유형을 알고하지 않기 때문에

public class GenericClass 
{ 
    public static object GetInstance(Type type) 
    { 
     var genericType = typeof(GenericClass<>).MakeGenericType(type); 
     return Activator.CreateInstance(genericType); 
    } 
} 

, 당신은 object하지만 아무것도 반환하지 (또는 dynamic)를 메서드에서 가져옵니다. 느린 100 배 이상

With Reflection: 243ms. 
Without Reflection: 2ms. 

그래서 조금 : 여기


는 (10 만 작성) 얼마나 느린

public class GenericClass 
{ 
    public static object GetInstance(Type type) 
    { 
     var genericType = typeof(GenericClass<>).MakeGenericType(type); 
     return Activator.CreateInstance(genericType); 
    } 

    public static GenericClass<T> GetInstance<T>() 
     where T : class 
    { 
     return new GenericClass<T>(); 
    } 
} 

    [Test] 
    public void CanMakeGenericViaReflection_ButItsSlow() 
    { 
     var timer = new Stopwatch(); 
     var SC = new SomeClass(); 
     SC.TypeOfAnotherClass = typeof(OneMoreClass); 

     timer.Start(); 
     for (int x = 0; x < 100000; x++) 
     { 
      GenericClass.GetInstance(SC.TypeOfAnotherClass); 
     } 
     timer.Stop(); 
     Console.WriteLine("With Reflection: " + timer.ElapsedMilliseconds + "ms."); 

     timer.Restart(); 
     for (int x = 0; x < 100000; x++) 
     { 
      GenericClass.GetInstance<OneMoreClass>(); 
     } 
     timer.Stop(); 
     Console.WriteLine("Without Reflection: " + timer.ElapsedMilliseconds + "ms."); 
    } 

결과입니다.

제네릭에 대해 주목해야 할 진짜는 제네릭의 <T> s는 C# 컴파일러에 의해 빌드 시간에서 해결하고 실제 클래스 이름이 삽입되어 있다는 것입니다. 런타임까지 실행을 연기해야하는 경우 성능 비용을 지불하게됩니다.

+0

얼마나 느린가요? – Gabe

+0

@Gabe - 리플렉션을 사용했을 때의 성능 저하를 보여주기 위해 필자의 대답에 더 많은 것을 추가했습니다. – CodingWithSpike

+0

"느림"은 "2 마이크로 초 걸립니다"를 의미합니다. 초당 수천 번만 수행하면 꽤 빠르지 만 수백만 번 수행해야하는 경우에는 너무 느립니다. – Gabe

1

정확히 무엇을 묻고 있는지 잘 모르겠습니다. OneMoreClass (당신은 당신이 실제로 원하는 유형을 알고있는 경우

Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic1.GetType()); 
Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic2.GetType()); 
관련 문제