加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-15 17:03:14 所属栏目:安全 来源:网络整理
导读:我有以下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.NameSp
我有以下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()行的错误,说新的不能用于接口类型.

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

我对F#编译器知之甚少,但你的评论很明显. C#和VB.NET编译器对COM内置有相当多的显式支持.请注意,您的语句在接口类型上使用new运算符,interop库中的Shell32.Shell如下所示:
[ComImport]
[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
[CoClass(typeof(ShellClass))]
public interface Shell : IShellDispatch6 {}

IShellDispatch6是真正的接口类型,您还可以通过IShellDispatch5接口查看IShellDispatch.这是过去20年工作中的版本控制,COM接口定义是不可变的,因为更改它们几乎总是在运行时导致无法识别的硬崩溃.

[CoClass]属性是这个故事的重要属性,这就是C#编译器在[ComImport]接口类型上使用new的要求.告诉它通过创建Shell32.ShellClass实例的实例来创建对象并获取Shell接口. F#编译器没有做什么.

ShellClass是一个假类,它由类型库导入器自动生成. COM从不公开具体类,它使用基于超纯接口的编程范例.对象始终由对象工厂创建,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.它还需要接口声明提供的IID,接口的[Guid].

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读