如何将以下COM接口转换为F#?我无法弄清楚如何注释属性的get
和set
。
另外,对于COM互操作,我是否需要使用get
注释属性本身及其DispId
?
[ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
private interface IWshShortcut
{
[DispId(0)]
string FullName { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0)] get; }
[DispId(0x3e8)]
string Arguments { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] set; }
[DispId(0x3ec)]
string RelativePath { [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ec)] set; }
[DispId(0x3ee)]
int WindowStyle { [DispId(0x3ee)] get; [param: In] [DispId(0x3ee)] set; }
[DispId(0x3ef)]
string WorkingDirectory { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] set; }
[TypeLibFunc((short)0x40), DispId(0x7d0)]
void Load([In, MarshalAs(UnmanagedType.BStr)] string PathLink);
[DispId(0x7d1)]
void Save();
}
答案 0 :(得分:6)
这是一个正确的,但不是字面意义的翻译:
[<ComImport; Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B"); TypeLibType(0x1040s)>]
type private IWshShortcut =
[<DispId(0)>]
abstract member FullName : [<MarshalAs(UnmanagedType.BStr)>] string with get
[<DispId(0x3e8)>]
abstract member Arguments : [<MarshalAs(UnmanagedType.BStr)>] string with get, set
[<DispId(0x3ec)>]
abstract member RelativePath : [<MarshalAs(UnmanagedType.BStr)>] string with set
[<DispId(0x3ee)>]
abstract member WindowStyle : int with get, set
[<DispId(0x3ef)>]
abstract member WorkingDirectory : [<MarshalAs(UnmanagedType.BStr)>] string with get, set
[<DispId(0x7d0); TypeLibFunc(0x40s)>]
abstract member Load : [<MarshalAs(UnmanagedType.BStr)>] PathLink:string -> unit
[<DispId(0x7d1)>]
abstract member Save : unit -> unit
正如您所发现的那样,您不能将属性添加到F#中的抽象属性的底层getter / setter方法,只能添加到属性本身,但它对于此特定接口并不重要:
get
和set
的字符串属性都需要相同的MarshalAs
。In
is the default directionality for string parameters,所以指明它无论如何都是多余的。DispId
应用于属性getter,因为您的C#代码是合法但无意义的 - 而DispId
可以应用于方法和属性,而属性getter和setter在技术上恰好是方法,属性只对属性本身有影响。 N.b。因为the CLR marshals string parameters for COM methods as BStrs by default,我们也可以省略所有MarshalAs
指令,并使它看起来更加微调(尽管不那么明确):
[<ComImport; Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B"); TypeLibType(0x1040s)>]
type private IWshShortcut =
[<DispId(0)>] abstract member FullName:string with get
[<DispId(0x3e8)>] abstract member Arguments:string with get, set
[<DispId(0x3ec)>] abstract member RelativePath:string with set
[<DispId(0x3ee)>] abstract member WindowStyle:int with get, set
[<DispId(0x3ef)>] abstract member WorkingDirectory:string with get, set
[<DispId(0x7d0); TypeLibFunc(0x40s)>] abstract member Load : PathLink:string -> unit
[<DispId(0x7d1)>] abstract member Save : unit -> unit
当然,所有这些都适用于C#实现,因此可以类似地简化:
[ComImport, Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B"), TypeLibType((short)0x1040)]
private interface IWshShortcut
{
[DispId(0)] string FullName { get; }
[DispId(0x3e8)] string Arguments { get; set; }
[DispId(0x3ec)] string RelativePath { set; }
[DispId(0x3ee)] int WindowStyle { get; set; }
[DispId(0x3ef)] string WorkingDirectory { get; set; }
[DispId(0x7d0), TypeLibFunc((short)0x40)] void Load(string PathLink);
[DispId(0x7d1)] void Save();
}