Почему это вызывает исключение InvalidClassCast?
По определенным причинам я должен предоставить вручную написанные вызываемые оболочки во время выполнения для ряда COM-компонентов, предлагаемых моим магазином.
Это определение интерфейса для компонента A:
[ComImport, Guid("02922621-2EAE-4442-8A0A-C1C3CD886027")]
public interface IProdistLogging
{
[DispId(1000)]
IProdistLoggingHierarchy CreateHierarchy ([MarshalAs(UnmanagedType.BStr)] string type, object configuration);
}
Это определение интерфейса для компонента B:
[ComImport, Guid("8D841E5C-F25B-4C12-B03A-70A899B3A32E")]
public interface ISts
{
[DispId(1001)]
IProdistLoggingHierarchy Logging { get; set; }
[DispId(1000)]
IStsSession CreateSession ();
}
Это определение интерфейса для компонента C:
[ComImport, Guid("13385FC6-2618-4830-A3A9-703398AA5A0B")]
public interface IStsRsfn
{
[DispId(1000)]
ISts Sts { get; set; }
[DispId(1010)]
IStsRsfnSession CreateSession();
}
Теперь следующая тестовая программа завершается с 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: это результат toString() для объекта исключения:
System.InvalidCastException: Specified cast is not valid.
at prodist.sts.rsfn.IStsRsfn.set_Sts(ISts value)
at sandbox.Program.Main(String[] args) in (...)
1 ответ
С тех пор мы обнаружили недостающую информацию, которая объясняет вышеуказанные симптомы: фактическое определение IDL для интерфейса.
Проблемная оболочка.NET не включала все методы соответствующего интерфейса, так что порядковый индекс для свойства Sts put в IDL и.NET не был одинаковым - даже если значение DispId является правильным.
После того, как мы обновили оболочку.NET, чтобы полностью отразить все методы из определения IDL - так, чтобы у каждого метода был тот же порядковый индекс, что и у другого - все работало.
Программист предположил, что методы были "смещены" в соответствии со значением атрибута DispId, но кажется, что они "смещены" на их фактическую позицию в списке методов от первого до последнего. Это подразумевает, что недопустимо предоставлять частичные обертки для интерфейсов - обертки, которые опускают определенные методы.