2010-07-28 8 views
17

CommandBase 클래스에서 상속하는 여러 클래스가 포함 된 dll이 있습니다. C#에서 리플렉션을 사용하여 이러한 모든 클래스 (CommandA, CommandB, CommandC 등)의 인스턴스를 가져 오려고합니다. 각 인스턴스에서 특정 메서드를 호출 할 수 있습니다. 여기에 내가 지금까지 가지고있는 것이있다 :리플렉션을 사용하여 dll의 특정 기본 유형의 모든 클래스 가져 오기

//get assemblies in directory. 
string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin"); 
var files = Directory.GetFiles(folder, "*.dll"); 
//load each assembly. 
foreach (string file in files) 
{ 
    var assembly = Assembly.LoadFile(file); 
    if (assembly.FullName == "MyCommandProject") 
    { 
    foreach (var type in assembly.GetTypes()) 
    { 
     if (!type.IsClass || type.IsNotPublic) continue; 
     if(type is CommandBase) 
     { 
     var command = Activator.CreateInstance(type) as CommandBase; 
     } 
    } 
    } 
} 

나는 2 개의 이슈를 가지고있다. 첫 번째 문제는 "if (type is CommandBase") 줄에 다음 경고가 표시된다는 것입니다.

제공된 표현식은 CommandBase 유형으로 제공되지 않습니다.

두 번째 문제는 실제 객체 (CommandA, CommandB 등 ...)의 인스턴스를 얻는 방법을 알아 내지 못하고 CommandBase로 변환하는 것으로 충분하지 않다는 것입니다.

+0

마지막 행에서 인스턴스가 제대로 생성되지 않습니까? 'Activator.CreateInstance()'를 사용하면 CommandA, CommandB ... class ('type'에 따라) 인스턴스가 있어야합니다. –

+0

Activation.CreateInstance()는 type 객체를 반환합니다. – Justin

+0

예. 제공 한 유형의 오브젝트를 리턴합니다. 당신은 "object"var 또는 "CommandBase"var에 저장할 수 있습니다. 여전히 CommandA, CommandB 등의 인스턴스가됩니다. 나중에 "진짜"유형으로 캐스팅 할 수 있습니다. 확인할 Visual Studio가 없지만 문제가 무엇인지 모르겠습니다. –

답변

29

이것은 인터페이스 기반으로로드하는 데 사용하는 방법입니다.

private static List<T> GetInstances<T>() 
{ 
     return (from t in Assembly.GetExecutingAssembly().GetTypes() 
       where t.GetInterfaces().Contains(typeof (T)) && t.GetConstructor(Type.EmptyTypes) != null 
       select (T) Activator.CreateInstance(t)).ToList(); 
} 

다음은 기본 클래스를 기반으로하는 동일한 기능입니다.

private static IList<T> GetInstances<T>() 
{ 
     return (from t in Assembly.GetExecutingAssembly().GetTypes() 
         where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null 
         select (T)Activator.CreateInstance(t)).ToList(); 
} 

물론로드하는 참조를 가리 키도록 약간 수정해야합니다.

+0

고맙지 만, 어떤 이유로 CommandBase 클래스를 상속 한 클래스가 아닌 CommandBase 클래스 만 반환합니다. 또한, "GetInstances ()"과 같이 호출하면 CommandBase 객체 목록이 표시됩니다. CommandA, CommandB 등 필요한 객체가 아닙니다.이 기능을 사용하려면 인터페이스를 사용해야하는 것처럼 들립니다. . – Justin

+0

CommandBase 클래스에 사용할 두 번째 함수를 추가했습니다. CommandBase에서 상속 한 클래스의 인스턴스 목록을 검색해야합니다. 그것을 간단한 스 니펫 테스트에 던지면 작동합니다. –

+0

나는 인터페이스를 사용하는 것으로 전환을 끝내고 첫 번째 코드 예제를 사용했습니다. 감사합니다! – Justin

2

type 변수가 CommandBase이 아닌 Type이기 때문입니다. 당신은 변경해야합니다 당신은 typeof(CommandBase).IsAssignableFrom(type)

+1

그게'if (type == typeof (CommandBase))'가 아니겠습니까? – Greg

+1

파생 된 클래스에서는 작동하지 않습니다. –

+1

결국 "is"대신 "=="이되었지만 작동했다. 고마워. 제 2 호에 대한 조언이 있습니까? – Justin

7

변경 type is CommandBase (보정에 대한 감사 그렉)

if(type == typeof(CommandBase)) 

을 원하는

if(type is CommandBase) 

if(type.IsSubclassOf(typeof(CommandBase))) 

IsSubclassOf가 IsAssignableFrom의 반대 인 경우. 즉, t1.IsSubclassOf (t2)가 true 인 경우 t2.IsAssignableFrom (t1)도 true입니다.

+0

+1 당신이 맞았 어 –

+0

+1 내가 입력했을 때 당신의 결과를 보지 못했지만,이 msdn은 "IsSubclassOf가 IsAssignableFrom의 반대라면."즉, t1.IsSubclassOf (t2)가 참이면 t2입니다. IsAssignableFrom (t1)도 참입니다. " 그래서 우리 둘 다 똑같이 옳았습니다, 나는 대답과 == 답을 지적하고있었습니다. –

6

+0

즉, 내 대답을 제외하고는 처음부터 정확했습니다. :)하지만 IsAssignableFrom을 사용하기 때문에 IsSubclassOf 메서드를 알아 차리지 못했기 때문에 +1을 제공합니다. –

관련 문제