2012-08-01 5 views
2

:유형 평등 검사</p> <pre><code>public abstract class CompositionPlugin { ... } </code></pre> <p>및</p> 내가 객체의 유형이 지정된 형태와 동일한 경우 검사 할 <pre><code>public class MyCompositionPlugin : CompositionPlugin { ... } </code></pre> <p>와

public class Framework { 

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>(); 

    public CompositionPlugin GetCompositionPlugin(Type ofType) 
    { 
     foreach (CompositionPlugin plugin in CompositionPlugins) 
     { 
      if (plugin.GetType().Equals(ofType)) 
       return plugin; 
     } 

     throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found"); 
    } 
} 

방법은 다음과 같이 호출되었습니다.

Framework framework = new Framework(); 
// Adding the plugin to the framework is done by loading an assembly and 
// checking if it contains plugin-compatible classes (i.e. subclasses 
// of <CompositionPlugin>) 
framework.RegisterAssembly("E:\\Projects\\Framework\\MyPlugin\\bin\\Debug\\MyPlugin.dll"); 
CompositionPlugin plugin = framework.GetCompositionPlugin(typeof(MyCompositionPlugin)); 

그러나 테스트 할 때 요청한 목록에 해당 유형의 개체가있는 경우에도이 검사는 항상 실패합니다.

제 생각에 CompositionPlugins -List 내에있는 MyCompositionPlugin의 첫 번째 인스턴스를 반환해야합니다.

내 형식 검사가 잘못 되었습니까? 왜? 어떻게 제대로 했습니까?

+0

몇 가지 코드를 추가하십시오. ofType 매개 변수는 어떻게 생성합니까? 왜 검사가 실패 했나요? 디버깅 해 봤어? –

+1

@tostringtheory는 정확한 유형을 반환합니다. CompositionPlugins를 상속받은 클래스 일 수 있습니다. –

+0

좀 더 많은 코드와 반환 값으로 기대되는 것을 추가했습니다. –

답변

0

내가 처음에 중요하지 그것을 간주하는 질문에서 제외 정보, 그래서 결국였다 밝혀졌습니다.

MyCompositionPluginCompositionPlugin은 실행중인 프로그램이 런타임에 동적으로로드된다는 점에서 서로 다른 어셈블리에 정의되어 있습니다.

는 .NET-런타임 해주기하더라도 ProgramMyCompositionPlugin - 유형 렌더링 실행 어셈블리에 의해 참조되는 하나보다 다른 어셈블리에서로드 MyCompositionPlugin에 부등 고려해야 할 또 다른 어셈블리에서로드 타입 consideres 그들은 실제로 동일합니다.

평등에 대한 두 가지 비교의 솔루션 (상식에서 "클래스"와 동일하다는 점에서)은 틀림없이 더러워진 정의 어셈블리의 문자열 - 동일성으로 분해하는 것이지만 장난. this question 지적 Paolo Falabella

public CompositionPlugin GetCompositionPlugin(Type ofType) 
{ 
    foreach (CompositionPlugin plugin in CompositionPlugins) 
     if (ofType.AssemblyQualifiedName.Equals(plugin.GetType().AssemblyQualifiedName)) 
      return plugin; 

    throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found"); 
} 

Cudos

3

사용 키워드 is

if (plugin is ofType) 
    return plugin; 

편집 :

나는이 일에 @vcsjones으로 가야 해요. isassignablefrom 기능을 사용하십시오.

하지만 실제로 그렇게해야한다고 생각한다면, 내가 항상하는 일은 디버그 텍스트를 파일에 작성하는 빠른 기능을 만드는 것입니다.

public class Framework { 

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>(); 

    public CompositionPlugin GetCompositionPlugin(Type ofType) 
    { 
     using(var writer = System.IO.File.CreateText(@"C:\test.log")) 
     { 
      writer.WriteLine("ofType: " + ofType.toString()); 
      foreach (CompositionPlugin plugin in CompositionPlugins) 
      { 
       writer.WriteLine("plugin: " + plugin.GetType().toString()); 
       if (plugin.GetType().Equals(ofType)) 
        return plugin; 
      } 
     } 

     throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found"); 
    } 
} 
+1

'is'에 실제 Type이 필요하므로 솔루션이 작동하지 않습니다. 나는 변수가있다. –

+2

그는'Type' 객체를 가지고 있습니다,'X is Type'는 작동하지 않습니다. – vcsjones

+0

@vcsjones가 말했듯이 이것은 작동하지 않지만 두 가지 이유로 작동하지 않습니다. 1. 유형의 인스턴스가 아니라 유형 이름이 필요합니다. 2. 'is'는 '평등'과 다릅니다. 'is'는 정확하게 또는 상속 된 형태입니다. '동등하다'는 정확히 맞습니다. –

7

당신은 당신의 유형에 IsAssignableFrom를 사용하려면 :

if (ofType.IsAssignableFrom(plugin.GetType()) 

Equals는 유형 정확히 동일한 경우를 처리합니다. IsAssignableFromofType이 플러그인에서 상속하는 유형이거나 구현 된 인터페이스 일 수있는 경우도 처리합니다.

+0

이것은 '평등'과 다릅니다. 당신은 또한 상속을 보호합니다. –

+0

@AmiramKorach 그게 핵심입니다. 제 생각에'ofType'은 모든 플러그인이 상속하거나 구현하는 어떤 유형의 기본 클래스 또는 인터페이스입니다. – vcsjones

4

대답이 없지만 댓글이 너무 길어 ... 방법을 호출하거나 컬렉션을 채우는 데 문제가없는 것은 확실합니까? 코드의 단순화 된 버전에 의해 입증 된 바와 같이 비교 자체는 확인을해야 : 지금

class A {} 

bool TestType(A item, Type ofType) 
{  
    return item.GetType().Equals(ofType); 
} 

:

Console.WriteLine(TestType(new A(), typeof(A))); // True 
Console.WriteLine(TestType(new A(), typeof(string))); // False 

편집

내가 @vcsjones 잘 생각합니다. 파생 클래스를 기본 클래스와 비교하려고합니다. foreach (CompositionPlugin plugin in CompositionPlugins) 라인에서 플러그인을 CompositionPlugin으로 선언하고 있지만 클라이언트 코드에서 이것을 typeof(MyCompositionPlugin)과 비교하고 있습니다.

:

는 당신과 같은 시나리오에서 같음에 대한 진실 테이블이 예제를 참조하십시오 (RE-EDIT 아니, 내가 틀렸다, 귀하의 경우는 true를 돌려 내 Console.WriteLine의의 4에 해당)

class CompositionPlugin {} 
class MyCompositionPlugin : CompositionPlugin {} 

// Define other methods and classes here 
bool TestType(CompositionPlugin item, Type ofType) 
{  
    return item.GetType().Equals(ofType); 
} 

지금

Console.WriteLine(TestType(new CompositionPlugin(), 
      typeof(CompositionPlugin))); //True 
Console.WriteLine(TestType(new CompositionPlugin(), 
      typeof(MyCompositionPlugin))); //False 
Console.WriteLine(TestType(new MyCompositionPlugin(), 
      typeof(CompositionPlugin))); //False 
Console.WriteLine(TestType(new MyCompositionPlugin(), 
      typeof(MyCompositionPlugin))); //True 
+0

메소드 주위에 더 많은 코드를 추가했습니다. 아마도이 문제가 해결 될 것입니다. 나는 또한 비교가 내가 원하는 방식으로 작동해야한다고 생각한다 ... –

+0

@FlorianPeschka는 코드를 보면 CompositionPlugin (CompositionPlugin에서 상속 한 것 같다)에 대해 CompositionPlugin을 검사하고있는 것으로 보인다. 나는 그것이 평등이 실패하는 이유라고 생각한다. 즉 vcsjones가 맞습니다. –

0

당신의 문제점은 어셈블리가 두 번째와로드는 사실 가능성이 높습니다 이에 대한 평등에 실패, 다시로드되는 어셈블리를 방지하는 것이 가장 좋습니다 따라서 더러운 문자열 비교를 사용해야하는 대신 일반 형식 비교를 사용할 수 있습니다. 나도 같은 문제가 생겼다. 플러그인 인터페이스는 별도의 어셈블리로 정의되었다.이 어셈블리는 시작 폴더에 있었지만 플러그 인 어셈블리에서 동적으로로드 된 결과 인터페이스 유형 동등성에 의해 실패했다. 플러그인 폴더에서 인터페이스 dll을 제거한 후 모든 것이 예상대로 작동했습니다.

관련 문제