這章中描述的屬性被用在創建和COM程序交互的程序中。
1.1 COMImport 屬性
當被放在一個類上, COMImport 屬性就把這個類標記為一個外部實現的COM 類。這樣的一個類聲明使得可以用一個C# 名稱調用一個COM 類。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Class)] 4 public class COMImportAttribute: System.Attribute 5 { 6 public COMImportAttribute() {…} 7 } 8 }
用COMImport 屬性修飾的類要受下面的限制:
- 它必須也被Guid 屬性修飾,它為被引入的COM類指定了CLSID 。如果一個類聲明包含COMImport 屬性,但是沒有包含Guid 屬性,就會發生一個編譯時錯誤。
- 它不能有任何成員。(一個沒有參數的公共構造函數會被自動提供。)
- 他必須從object類派生。
示例
1 using System.Runtime.InteropServices; 2 [COMImport, Guid("00020810-0000-0000-C000-000000000046")] 3 class Worksheet {} 4 class Test 5 { 6 static void Main() { 7 Worksheet w = new Worksheet(); // Creates an Excel worksheet 8 } 9 }
聲明了一個類Worksheet ,這個類作為一個類從有CLSID “00020810-0000-0000-C000-000000000046″的COM引入。一個Worksheet 實例的實例化造成了一個相應的COM實例化。
1.2 COMRegisterFunction 屬性
一個方法中的COMRegisterFunction 屬性的實現,指示出這個方法應該在COM注冊過程中被調用。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Method)] 4 public class COMRegisterFunctionAttribute: System.Attribute 5 { 6 public ComRegisterFunctionAttribute() {…} 7 } 8 }
1.3 COMSourceInterfaces 屬性
COMSourceInterfaces 屬性用來列出引入的聯合類中的源接口。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Class)] 4 public class ComSourceInterfacesAttribute: System.Attribute 5 { 6 public ComSourceInterfacesAttribute(string value) {…} 7 public string Value { get {…} } 8 } 9 }
1.4 COMVisible 屬性
COMVisible 屬性用來指定一個類或接口在COM中是否可見。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] 4 public class COMVisibleAttribute: System.Attribute 5 { 6 public COMVisibleAttribute(bool value) {…} 7 public bool Value { get {…} } 8 } 9 }
1.5 DispId 屬性
DispId 屬性被用來指定一個OLE 的自動化 DISPID。一個DISPID 是一個整數類型數值,它在dispinterface中指定一個成員。
namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)] public class DispIdAttribute: System.Attribute { public DispIdAttribute(int value) {…} public int Value { get {…} } } }
1.6 DllImport 屬性
DllImport 屬性用來指定包含一個外部方法的實現程序的dll的位置。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Method)] 4 public class DllImportAttribute: System.Attribute 5 { 6 public DllImportAttribute(string dllName) {…} 7 public CallingConvention CallingConvention; 8 public CharSet CharSet; 9 public string EntryPoint; 10 public bool ExactSpelling; 11 public bool SetLastError; 12 public bool TransformSig; 13 public string Value { get {…} } 14 } 15 }
特別地, DllImport 屬性友下面的行為:
- 它只能用在方法聲明中。
- 它有一個位置參數: dllName 參數,指定包含要引入的方法的dll的名稱。
- 他有五個名稱參數:
- 它是一個單次使用屬性類。
- CallingConvention 參數指定為入口點調用的轉換。如果沒有指定CallingConvention ,默認的CallingConvention.Winapi 就會被使用。
- CharSet 參數指定用於入口點的字符集。如果沒有CharSet 被指定,就會使用默認的CharSet.Auto。
- EntryPoint 參數給出dll中的入口點的名稱。如果沒有EntryPoint 被指定,就會使用方法自己的名稱。
- ExactSpelling 參數指定是否EntryPoint 必須與指出的入口點的拼寫相匹配。如果沒有指定ExactSpelling ,就會使用默認得false。
- SetLastError 參數指出方法是否保存Win32 的”最后的錯誤”。如果沒有指定SetLastError ,就會使用默認的false。
- TransformSig 參數指出是否要為返回數值把方法的簽名轉換為一個有HRESULT 返回值和有附加的外部參數的稱為retval量的返回數值。如果沒有指定TransformSig 數值,就會使用默認得false。
另外,一個被DllImport 屬性修飾的方法必須有extern 修飾符。
1.7 FieldOffset 屬性
FieldOffset 屬性被用來為結構指定域的規划。
namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Field)] public class FieldOffsetAttribute: System.Attribute { public FieldOffsetAttribute(int value) {…} public int Value { get {…} } } }
FieldOffset 屬性也許不會被放在一個作為類的成員的域聲明中。
1.8 GlobalObject 屬性
GlobalObject 屬性的存在指定一個類是COM中的”全局” 或 ”appobject” 類。
namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class)] public class GlobalObjectAttribute: System.Attribute { public GlobalObjectAttribute() {…} } }
1.9 Guid 屬性
Guid 屬性用來為一個類或一個接口指定一個全局的唯一標識符 (GUID)。這個信息主要用於與COM的互用性中。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Class 4 | AttributeTargets.Interface 5 | AttributeTargets.Enum 6 | AttributeTargets.Delegate 7 | AttributeTargets.Struct)] 8 public class GuidAttribute: System.Attribute 9 { 10 public GuidAttribute(string value) {…} 11 public string Value { get {…} } 12 } 13 }
位置字符串參數的形式在編譯時被驗證。指定一個在不是句法上有效的GUID的字符串參數是錯誤的。
1.10 HasDefaultInterface 屬性
如果存在, HasDefaultInterface 屬性指出一個類游一個默認接口。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Class)]
public class HasDefaultInterfaceAttribute: System.Attribute
{
public HasDefaultInterfaceAttribute() {…}
}
}
1.11 ImportedFromTypeLib 屬性
ImportedFromTypeLib 屬性被用來指定一個模塊從COM類型庫中被引入。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Module)]
public class ImportedFromTypeLib: System.Attribute
{
public ImportedFromTypeLib(string value) {…}
public string Value { get {..} }
}
}
1.12 In 和 Out 屬性
In 和 Out 屬性被用來為參數提供自定義集合信息。這些集合屬性的所有組合都是允許的。
1 namespace System.Runtime.InteropServices 2 { 3 [AttributeUsage(AttributeTargets.Parameter)] 4 public class InAttribute: System.Attribute 5 { 6 public InAttribute() {…} 7 } 8 [AttributeUsage(AttributeTargets.Parameter)] 9 public class OutAttribute: System.Attribute 10 { 11 public OutAttribute() {…} 12 } 13 }
如果一個參數沒有被任何集合屬性修飾,那么它就是基於它的參數修飾符,就像下面一樣。如果參數沒有修飾符,那么集合是 [In]。 如果參數有ref 修飾符,那么集合是 [In, Out]。 如果參數有out修飾符,那么集合是 [Out]。
注意out是一個關鍵字,而Out是一個屬性。示例
1 class Class1 2 { 3 void M([Out] out i, nt i) { 4 … 5 } 6 }
介紹了把out當作參數修飾符的使用和在一個屬性中的Out的使用。
1.13 InterfaceType 屬性
當放在一個接口上, InterfaceType 屬性指定了接口在COM被看作的樣式。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Interface)]
public class InterfaceTypeAttribute: System.Attribute
{
public InterfaceTypeAttribute(ComInterfaceType value) {…}
public ComInterfaceType Value { get {…} }
}
}
1.14 MarshalAs 屬性
MarshalAs 屬性被用來描述一個域、方法或參數的集合形式。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method |
AttributeTargets.Parameter |
AttributeTargets.Field)]
public class MarshalAsAttribute: System.Attribute
{
public MarshalAsAttribute(UnmanagedType unmanagedType) {…}
public UnmanagedType ArraySubType;
public string MarshalCookie;
public string MarshalType;
public string MarshalTypeLibGuid;
public string MarshalUnmanagedType;
public VarEnum SafeArraySubType;
public int SizeConst;
public short SizeParamIndex;
public int SizeParamMultiplier;
}
}
1.15 NoIDispatch 屬性
NoIDispatch 屬性的存在指示當要輸出到COM時,類或接口要從IUnknown 中派生而不是IDispatch 。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class NoIDispatchAttribute: System.Attribute
{
public NoIDispatchAttribute() {…}
}
}
1.16 NonSerialized 屬性
NonSerialized 屬性的存在於一個域和屬性中,指出那個域或屬性要被特殊化。
namespace System
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class NonSerializedAttribute: Attribute
{
public NonSerializedAttribute() {…}
}
}
1.17 Predeclared 屬性
Predeclared 屬性的存在表示一個預聲明的對象從COM引入。
namespace System.Runtime.InteropServices
{
[AttributeUsage(Attribute(AttributeTargets.Class)]
public class PredeclaredAttribute: System.Attribute
{
public PredeclaredAttribute() {…}
}
)
1.18 PreserveSig 屬性
PreserveSig 屬性被用來把一個方法標記為在COM中返回HRESULT 結果。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public class PreserveSigAttribute: System.Attribute
{
public PreserveSigAttribute(bool value) {…}
public bool Value { get {…} }
}
}
PreserveSig 屬性被用來指出,通常在互用性調用中發生的HRESULT/retval 簽名轉換應該被禁止。
1.19 Serializable 屬性
Serializable 屬性存在於一個類中表示那個類要被特殊化。
namespace System
{
[AttributeUsage(AttributeTargets.Class
| AttributeTargets.Delegate
| AttributeTargets.Enum
| AttributeTargets.Struct)]
public class SerializableAttribute: System.Attribute
{
public SerializableAttribute() {…}
}
}
1.20 StructLayout 屬性
StructLayout 屬性被用來為一個結構指定域的布局。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class StructLayoutAttribute: System.Attribute
{
public StructLayoutAttribute(LayoutKind value) {…}
public CharSet CharSet;
public bool CheckFastMarshal;
public int Pack;
public LayoutKind Value { get {…} }
}
}
如果LayoutKind.Explicit 被指定,那么在結構中的每個域必須都有StructOffset 屬性。如果LayoutKind.Explicit 沒有被指定,那么StructOffset 屬性的使用就被禁止了。
1.21 TypeLibFunc 屬性
TypeLibFunc 屬性被用來指定typelib 標記,用於與COM互用。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method)]
public class TypeLibFuncAttribute: System.Attribute
{
public TypeLibFuncAttribute(TypeLibFuncFlags value) {…}
public TypeLibFuncFlags Value { get {…} }
}
}
1.22 TypeLibType 屬性
TypeLibType 屬性被用來指定typelib 標記,用於與COM互用。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class TypeLibTypeAttribute: System.Attribute
{
public TypeLibTypeAttribute(TypeLibTypeFlags value) {…}
public TypeLibTypeFlags Value { get {…} }
}
}
1.23 TypeLibVar 屬性
TypeLibVar屬性被用來指定typelib 標記,用於與COM互用。
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Field)]
public class TypeLibVarAttribute: System.Attribute
{
public TypeLibVarAttribute(TypeLibVarFlags value) {…}
public TypeLibVarFlags Value { get {…} }
}
}
1.24 支持的枚舉
namespace System.Runtime.InteropServices
{
public enum CallingConvention
{
Winapi = 1,
Cdecl = 2,
Stdcall = 3,
Thiscall = 4,
Fastcall = 5
}
public enum CharSet
{
None,
Auto,
Ansi,
Unicode
}
public enum ComInterfaceType
{
InterfaceIsDual = 0,
InterfaceIsIUnknown = 1,
InterfaceIsIDispatch = 2,
}
public enum LayoutKind
{
Sequential,
Union,
Explicit,
}
public enum TypeLibFuncFlags
{
FRestricted = 1,
FSource = 2,
FBindable = 4,
FRequestEdit = 8,
FDisplayBind = 16,
FDefaultBind = 32,
FHidden = 64,
FUsesGetLastError = 128,
FDefaultCollelem = 256,
FUiDefault = 512,
FNonBrowsable = 1024,
FReplaceable = 2048,
FImmediateBind = 4096
}
public enum TypeLibTypeFlags
{
FAppObject = 1,
FCanCreate = 2,
FLicensed = 4,
FPreDeclId = 8,
FHidden = 16,
FControl = 32,
FDual = 64,
FNonExtensible = 128,
FOleAutomation = 256,
FRestricted = 512,
FAggregatable = 1024,
FReplaceable = 2048,
FDispatchable = 4096,
FReverseBind = 8192
}
public enum TypeLibVarFlags
{
FReadOnly = 1,
FSource = 2,
FBindable = 4,
FRequestEdit = 8,
FDisplayBind = 16,
FDefaultBind = 32,
FHidden = 64,
FRestricted = 128,
FDefaultCollelem = 256,
FUiDefault = 512,
FNonBrowsable = 1024,
FReplaceable = 2048,
FImmediateBind = 4096
}
public enum UnmanagedType
{
Bool = 0×2,
I1 = 0×3,
U1 = 0×4,
I2 = 0×5,
U2 = 0×6,
I4 = 0×7,
U4 = 0×8,
I8 = 0×9,
U8 = 0xa,
R4 = 0xb,
R8 = 0xc,
BStr = 0×13,
LPStr = 0×14,
LPWStr = 0×15,
LPTStr = 0×16,
ByValTStr = 0×17,
Struct = 0x1b,
Interface = 0x1c,
SafeArray = 0x1d,
ByValArray = 0x1e,
SysInt = 0x1f,
SysUInt = 0×20,
VBByRefStr