gpt4 book ai didi

f# - 如何将使用 Shell COM 的 C# 代码转换为 F#?

转载 作者:行者123 更新时间:2023-12-04 17:32:53 29 4
gpt4 key购买 nike

我有以下 C# 方法:

private static bool IsLink(string shortcutFilename)
{
var pathOnly = Path.GetDirectoryName(shortcutFilename);
var filenameOnly = Path.GetFileName(shortcutFilename);

var shell = new Shell32.Shell();
var folder = shell.NameSpace(pathOnly);
var folderItem = folder.ParseName(filenameOnly);
return folderItem != null && folderItem.IsLink;
}

我尝试将其转换为 F#:
let private isLink filename =
let pathOnly = Path.GetDirectoryName(filename)
let filenameOnly = Path.GetFileName(filename)
let shell = new Shell32.Shell()
let folder = shell.NameSpace(pathOnly)
let folderItem = folder.ParseName(filenameOnly)
folderItem <> null && folderItem.IsLink

然而,它报告了 let shell = new Shell32.Shell() 的错误。行,说 new不能用于接口(interface)类型。

我只是犯了一个愚蠢的语法错误,还是需要额外的工作才能从 F# 访问 COM?

最佳答案

我对 F# 编译器知之甚少,但您的评论足以说明这一点。 C# 和 VB.NET 编译器对内置 COM 有相当多的显式支持。请注意,您的语句使用 new接口(interface)类型上的运算符,互操作库中的 Shell32.Shell 如下所示:

[ComImport]
[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
[CoClass(typeof(ShellClass))]
public interface Shell : IShellDispatch6 {}

IShellDispatch6 是真正的接口(interface)类型,通过IShellDispatch5 接口(interface)也可以看到IShellDispatch。这是过去 20 年工作中的版本控制,COM 接口(interface)定义是不可变的,因为更改它们几乎总是会在运行时导致无法诊断的硬崩溃。

[CoClass] 属性是这个故事的重要属性,这就是 C# 编译器寻找你使用的 new在 [ComImport] 接口(interface)类型上。告诉它通过创建 Shell32.ShellClass 的实例来创建对象实例并获取Shell接口(interface)。 F# 编译器不做什么。
ShellClass类,它是由类型库导入器自动生成的。 COM 从不公开具体的类,它使用基于超纯接口(interface)的编程范式。对象总是由对象工厂创建, CoCreateInstance()是主力。本身就是一个方便的功能,真正的工作是由万能的 IClassFactory interface来完成的,超纯的风格。每个 COM coclass 都实现了它的 CreateInstance() 方法。

类型库导入器使 ShellClass 看起来像这样:
[ComImport]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("13709620-C279-11CE-A49E-444553540000")]
public class ShellClass : IShellDispatch6, Shell {
// Methods
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x60040000)]
public virtual extern void AddToRecent([In, MarshalAs(UnmanagedType.Struct)] object varFile, [In, Optional, MarshalAs(UnmanagedType.BStr)] string bstrCategory);
// Etc, many more methods...
}

大量的火和运动,都不应该使用。唯一真正重要的是 [Guid] 属性,它提供了 CoCreateInstance() 需要的 CLSID。它还需要接口(interface)声明提供的 IID,即接口(interface)的 [Guid]。

因此,F# 中的解决方法是创建 Shell32.ShellClass 对象,就像 C# 编译器隐式执行的那样。虽然从技术上讲,您可以将引用保留在 ShellClass 变量中,但您应该强烈支持接口(interface)类型。 COM方式,纯方式,避免 this kind of problem .最终是 CLR 完成了工作,它在其 new 中识别 ShellClass 类声明中的 [ClassInterface] 属性。运营商实现。 .NET 中更明确的方法是使用 Type.GetTypeFromCLSID() 和 Activator.CreateInstance(),当您只有 coclass 的 Guid 时很方便。

关于f# - 如何将使用 Shell COM 的 C# 代码转换为 F#?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37145234/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com