2010-05-28 11 views
0

현재 인터페이스를 일반 매개 변수 (생성자에서 적용됨)로 가져오고로드 된 모든 어셈블리의 모든 유형에서 해당 인터페이스를 구현하는 인스턴스화 된 객체를 가져올 수 있도록 일반 인스턴스 팩토리를 만들려고합니다. 다음과 같이반사 구체화

현재 구현은 다음과 같습니다

public class InstantiationFactory<T> 
{ 
    protected Type Type { get; set; } 

    public InstantiationFactory() 
    { 
     this.Type = typeof(T); 
     if (!this.Type.IsInterface) 
     { 
      // is there a more descriptive exception to throw? 
      throw new ArgumentException(/* Crafty message */); 
     } 
    } 

    public IEnumerable<Type> GetLoadedTypes() 
    { 
     // this line of code found in other stack overflow questions 
     var types = AppDomain.CurrentDomain.GetAssemblies() 
      .SelectMany(a => a.GetTypes()) 
      .Where(/* lambda to identify instantiable types which implement this interface */); 

     return types; 
    } 

    public IEnumerable<T> GetImplementations(IEnumerable<Type> types) 
    { 
     var implementations = types.Where(/* lambda to identify instantiable types which implement this interface */ 
      .Select(x => CreateInstance(x)); 

     return implementations; 
    } 

    public IEnumerable<T> GetLoadedImplementations() 
    { 
     var loadedTypes = GetLoadedTypes(); 
     var implementations = GetImplementations(loadedTypes); 
     return implementations; 
    } 

    private T CreateInstance(Type type) 
    { 
     T instance = default(T); 

     var constructor = type.GetConstructor(Type.EmptyTypes); 
     if (/* valid to instantiate test */) 
     { 
      object constructed = constructor.Invoke(null); 
      instance = (T)constructed; 
     } 

     return instance; 
    } 
} 

내가 나중에 다시 내 공장의 코드를 단순화 할 수 있도록 내 CreateInstance(Type) 기능 확장 방법으로 구현이 나에게 유용 할 것 같습니다,하지만 난 할 수 그 확장 메서드에서 강력한 형식의 값을 반환하는 방법을 알아낼 수 없습니다.

public static class TypeExtensions 
{ 
    public object CreateInstance(this Type type) 
    { 
     var constructor = type.GetConstructor(Type.EmptyTypes); 
     return /* valid to instantiate test */ ? constructor.Invoke(null) : null; 
    } 
} 

이 확장 방법은 확장 유형의 인스턴스 당 서명을 만드는 것이 가능하다 :

는 난 그냥 객체를 반환 할 수 실현?

내 완벽한 코드는 CreateInstance()에 호출의 결과를 주조하는 것을 피한다되는이 될 것입니다 :

Type type = typeof(MyParameterlessConstructorImplementingType); 
MyParameterlessConstructorImplementingType usable = type.CreateInstance(); 
+0

... 내 전화 –

답변

2

당신이 컴파일 시간 유형을 얻으려고 노력하기 때문에 나는 '돈은 가능하다고 생각 런타임에만 알 수있는 유형의 정보 (강력한 입력). 인터페이스로 작업해야합니다.

문제는 컴파일 타임에 어셈블리에 어떤 유형이 포함되는지 알지 못하기 때문입니다. 어셈블리 이름에 변수를 사용할 수도 있습니다! 어셈블리에는 인터페이스 구현이 포함될 수 있습니다. 따라서 어셈블리에서로드하는 유형의 강력한 유형의 인스턴스를 컴파일러에 생성하도록 컴파일러에 지시 할 필요가 없습니다.

0

어쩌면 이렇게 할 수 있을까요? 내부적으로 캐스트를 처리하기 위해 캐스트 또는 제네릭 형식 매개 변수 없이는 방법이 표시되지 않습니다. 나는 하위 클래스 Type 객체가 들어있는 곳과 비슷한 것을 사용하지만 호출자는 기본 클래스 메소드 만 사용한다.

public static object New(this Type type) 
{ 
    return type.GetConstructor(Type.EmptyTypes).Invoke(null); 
} 

public static T New<T>(this Type type) 
{ 
    return (T)type.GetConstructor(Type.EmptyTypes).Invoke(null); 
} 

// usage 
MyParameterless usable = (MyParameterless)type.New(); 
MyParameterless usable 2 = type.New<MyParameterless>(); 
+0

당신의 접근 방식의 문제점에 게시하면 유형을 알고 있다는 점이다 (당신도를 기록한 'MyParemeterless를'). 그는 조립에서 그것을로드하지 않습니다. – Simon

+0

수정. simlilar를 사용하는 코드에서 실제 런타임 유형을 모르지만 기본 형식을 알고 있습니다. 이것들은 (내가 쓰지 않은) 어셈블리에서도로드됩니다. 그가 사용한 사용 예를 참조하십시오 'Type type = typeof (MyParameterlessConstructorImplementingType); MyParameterlessConstructorImplementingType 사용 가능 = type.CreateInstance(); ' 및 내 게시물 '나는 ...없이 방법을 볼 수 없습니다 자격이 문장 ... –

0

제약 조건이있는 확장 방법에서 제네릭을 사용하지 않으시겠습니까? 망가 텍스트 죄송합니다

public static class TypeExtensions 
{ 
    public T CreateInstance<T>(this T type) where T : Type 
    { 
     var constructor = type.GetConstructor(Type.EmptyTypes); 
     return /* valid to instantiate test */ ? constructor.Invoke(null) : null; 
    } 
}