2015-02-04 3 views
0

특정 이유로 인해 필자가 제공하는 여러 COM 구성 요소에 대해 수동으로 작성된 런타임 호출 가능 래퍼를 제공해야합니다.왜 InvalidClassCast 예외가 발생합니까?

[ComImport, Guid("13385FC6-2618-4830-A3A9-703398AA5A0B")] 
public interface IStsRsfn 
{ 
    [DispId(1000)] 
    ISts Sts { get; set; } 

    [DispId(1010)] 
    IStsRsfnSession CreateSession(); 
} 
:

[ComImport, Guid("8D841E5C-F25B-4C12-B03A-70A899B3A32E")] 
public interface ISts 
{ 
    [DispId(1001)] 
    IProdistLoggingHierarchy Logging { get; set; } 

    [DispId(1000)] 
    IStsSession CreateSession(); 
} 

이 성분 C에 대한 인터페이스 정의가 :

[ComImport, Guid("02922621-2EAE-4442-8A0A-C1C3CD886027")] 
public interface IProdistLogging 
{ 
    [DispId(1000)] 
    IProdistLoggingHierarchy CreateHierarchy ([MarshalAs(UnmanagedType.BStr)] string type, object configuration); 
} 

이 성분 B에 대한 인터페이스 정의가 :

은 성분 A를위한 인터페이스의 정의이며

이제 다음 테스트 프로그램이 InvalidCastException과 함께 종료됩니다.

public static void Main (string[] args) 
{ 
    IProdistLogging logging = (IProdistLogging)System.Activator.CreateInstance(Type.GetTypeFromProgID("prodist.logging.Logging.5.4")); 
    IProdistLoggingHierarchy loggingHierarchy = logging.CreateHierarchy("log4cxx", null); 
    ISts sts = (ISts)System.Activator.CreateInstance(Type.GetTypeFromProgID("prodist.sts.Sts.5.4")); 
    sts.Logging = loggingHierarchy; 
    IStsRsfn rsfn = (IStsRsfn)System.Activator.CreateInstance(Type.GetTypeFromProgID("prodist.sts.rsfn.StsRsfn.5.4")); 

    // The following statement raises an InvalidCastException 
    // with message "Specified cast is not valid" 
    rsfn.Sts = sts; 

    IStsRsfnSession session = rsfn.CreateSession(); 
    return; 
} 

왜 이렇게 될까요?

편집 1 : 인터페이스에 대한 실제 IDL 정의 : 우리는 이후 위의 증상을 설명 누락 된 정보를 발견했다

System.InvalidCastException: Specified cast is not valid. 
    at prodist.sts.rsfn.IStsRsfn.set_Sts(ISts value) 
    at sandbox.Program.Main(String[] args) in (...) 
+0

* 전체 * 예외 메시지를 게시해야합니다. 달러 도넛, COM 서버에 프록시가 없습니다. Main() 메소드에 [STAThread]를 넣지 않아도된다. 그건 맞지 않지만 적어도 가능한 문제를 제거 할 것입니다. –

답변

0

:이 예외 객체에 toString()의 결과이다.

문제가있는 .NET 래퍼에는 해당 인터페이스의 모든 메서드가 포함되어 있지 않으므로 DispId 값이 올바르더라도 IDL 및 .NET에있는 Sts put 속성의 서수 인덱스가 동일하지 않습니다.

.NET 랩퍼를 업데이트 한 후 각 메서드가 다른 인덱스 인덱스와 동일한 순서로 IDL 정의의 모든 메서드를 완벽하게 반영했습니다.

프로그래머는 메서드가 DispId 특성의 값에 따라 "오프셋"되어 있다고 가정했지만 처음부터 마지막까지 메서드 목록에서 실제 위치에 의해 "오프셋"된 것처럼 보입니다. 이는 인터페이스에 대한 부분 랩퍼 (특정 메소드를 생략 한 랩퍼)를 제공하는 것이 적법하지 않음을 의미합니다.