我可以简化 ComImport 中未使用的方法签名吗?
Can I simplify method signatures I am not using in a ComImport?
我想在 IWiaDevMgr2
上给 GetImageDlg
打电话。有许多非常复杂的方法(我没有使用)引用了许多类型(我也没有使用)。由于找不到可自动生成我的 ComImport
的 TLB 或 IDL,因此我宁愿避免手动翻译所有引用的类型。
我可以 "skip" 方法和类型替换为 from
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2
{
IEnumWIA_DEV_INFO EnumDeviceInfo(
int lFlags);
IWiaItem2 CreateDevice(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID);
// ...snip five other method declarations...
IWiaItem2 GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
到
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void VTablePlaceholder0();
void VTablePlaceholder1();
void VTablePlaceholder2();
void VTablePlaceholder3();
void VTablePlaceholder4();
void VTablePlaceholder5();
void VTablePlaceholder6();
[return: MarshalAs(UnmanagedType.Interface)]
object GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
一切似乎 工作正常,只要我不调用任何占位符。我可以这样做而不会产生任何后果吗?
当然可以。您是唯一一个将使用此接口定义的人,所以没关系。
当然,如果此接口用作从本机到托管的回调,那将是一个问题,但在这种情况下,您将以某种方式实现它。实施此类虚拟方法预示着未来会出现问题。
请注意,有一种官方方法可以做到这一点。您可以为占位符使用一个特殊的 _VtblGap{0}_{1}
名称,其中 0 是一个索引,1 是您要跳过的方法数。
在此处查看 Roslyn 中的实现(它也在公共语言基础结构规范中):https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/ModuleExtensions.cs
// From IMetaDataEmit::DefineMethod documentation (http://msdn.microsoft.com/en-us/library/ms230861(VS.100).aspx)
// ----------------------
// In the case where one or more slots need to be skipped, such as to preserve parity with a COM interface layout,
// a dummy method is defined to take up the slot or slots in the v-table; set the dwMethodFlags to the mdRTSpecialName
// value of the CorMethodAttr enumeration and specify the name as:
//
// _VtblGap<SequenceNumber><_CountOfSlots>
//
// where SequenceNumber is the sequence number of the method and CountOfSlots is the number of slots to skip in the v-table.
// If CountOfSlots is omitted, 1 is assumed.
// ----------------------
//
// From "Partition II Metadata.doc"
// ----------------------
// For COM Interop, an additional class of method names are permitted:
// _VtblGap<SequenceNumber><_CountOfSlots>
// where <SequenceNumber> and <CountOfSlots> are decimal numbers
// ----------------------
所以在你的情况下,它将是:
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void _VtblGap1_7(); // skip seven methods
...
};
我想在 IWiaDevMgr2
上给 GetImageDlg
打电话。有许多非常复杂的方法(我没有使用)引用了许多类型(我也没有使用)。由于找不到可自动生成我的 ComImport
的 TLB 或 IDL,因此我宁愿避免手动翻译所有引用的类型。
我可以 "skip" 方法和类型替换为 from
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2
{
IEnumWIA_DEV_INFO EnumDeviceInfo(
int lFlags);
IWiaItem2 CreateDevice(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID);
// ...snip five other method declarations...
IWiaItem2 GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
到
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void VTablePlaceholder0();
void VTablePlaceholder1();
void VTablePlaceholder2();
void VTablePlaceholder3();
void VTablePlaceholder4();
void VTablePlaceholder5();
void VTablePlaceholder6();
[return: MarshalAs(UnmanagedType.Interface)]
object GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
一切似乎 工作正常,只要我不调用任何占位符。我可以这样做而不会产生任何后果吗?
当然可以。您是唯一一个将使用此接口定义的人,所以没关系。
当然,如果此接口用作从本机到托管的回调,那将是一个问题,但在这种情况下,您将以某种方式实现它。实施此类虚拟方法预示着未来会出现问题。
请注意,有一种官方方法可以做到这一点。您可以为占位符使用一个特殊的 _VtblGap{0}_{1}
名称,其中 0 是一个索引,1 是您要跳过的方法数。
在此处查看 Roslyn 中的实现(它也在公共语言基础结构规范中):https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/ModuleExtensions.cs
// From IMetaDataEmit::DefineMethod documentation (http://msdn.microsoft.com/en-us/library/ms230861(VS.100).aspx)
// ----------------------
// In the case where one or more slots need to be skipped, such as to preserve parity with a COM interface layout,
// a dummy method is defined to take up the slot or slots in the v-table; set the dwMethodFlags to the mdRTSpecialName
// value of the CorMethodAttr enumeration and specify the name as:
//
// _VtblGap<SequenceNumber><_CountOfSlots>
//
// where SequenceNumber is the sequence number of the method and CountOfSlots is the number of slots to skip in the v-table.
// If CountOfSlots is omitted, 1 is assumed.
// ----------------------
//
// From "Partition II Metadata.doc"
// ----------------------
// For COM Interop, an additional class of method names are permitted:
// _VtblGap<SequenceNumber><_CountOfSlots>
// where <SequenceNumber> and <CountOfSlots> are decimal numbers
// ----------------------
所以在你的情况下,它将是:
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void _VtblGap1_7(); // skip seven methods
...
};