前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VisualStudio 开发文件自定义工具单文件生成工具

VisualStudio 开发文件自定义工具单文件生成工具

作者头像
林德熙
发布2020-07-07 15:06:26
4180
发布2020-07-07 15:06:26
举报
文章被收录于专栏:林德熙的博客林德熙的博客

在 VisualStudio 右击任意的文件夹,点击属性,可以看到属性里面有一个选项是自定义工具。如果创建的是 WPF 项目,可以看到页面或用户控件的自定义工具是 XamlIntelliSenseFileGenerator 可以用来在设计时转换文件,将转换的输出放在另一个文件中。通过这个方法可以自己定义一些内容,在修改内容文件的时候自动生成代码

我最近在做优化,我想将一个自定义的 yml 文件编译为一个类,这样我可以提高软件的运行速度。我想做到和编译 xaml 一样,在 xaml 修改的时候就自动将 yml 编译为一个类,于是我就找到了自定义工具

本文的方法将是在 VisualStudio 2019 使用的方法,在 VisualStudio 2019 的特性 就提供了新的插件 Nuget 包使用方法十分简单

在安装 Visual Studio 2019 的时候,可以选择插件开发,这时可以在新的欢迎界面快速创建插件

现在创建的插件默认给的是 AsyncPackage 而不是之前的 Package 这个类不需要修改内容

创建一个新的类,这个类继承 IVsSingleFileGenerator 接口,这样就可以用来创建文件了。在继承这个接口之后,可以发现需要重写两个方法,第一个方法是 DefaultExtension 方法,这个方法需要返回转换创建的文件的后缀名,同时返回后缀名的字符长度

代码语言:javascript
复制
        public int DefaultExtension(out string defaultExtension)
        {
            defaultExtension = ".generated.cs";
            return defaultExtension.Length;
        }

在自定义工具可以自动创建一个和设置自定义工具的文件的相同命名的文件,只是这个文件的后缀名修改为这个方法返回的后缀名。因为这个方法可能是会被一些不清真的代码使用,所以需要返回当前的字符串的长度

第二个方法是 Generate 这是一个核心的方法,在设置使用自定义工具的文件被更改的时候,将会自动调用这个方法。在这个方法的输出里面相对有一些坑,我想要输出林德熙是逗比这个字符串到文件,我需要使用下面代码

代码语言:javascript
复制
        public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
        {
            var bytes = Encoding.UTF8.GetBytes("林德熙是逗比");
            var length = bytes.Length;

            rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length);
            Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length);
            pcbOutput = (uint) length;

            return VSConstants.S_OK;
        }

这个方法的参数含义

  • wszInputFilePath 文件的绝对路径
  • bstrInputFileContents 文件的内容,可能出现编码问题
  • wszDefaultNamespace 建议的命名空间
  • rgbOutputFileContents 输出的内容
  • pcbOutput 输出的长度

需要将输出的字符串先转 byte 数组,然后赋值给输出的内容返回输出内容的长度。还需要在赋值之前先申请一段内存

当然为了让 VisualStudio 能发现这个类,需要添加一些特性

代码语言:javascript
复制
    [ComVisible(true)]
    [Guid(FilePluralizationGeneratorId)]
    [CodeGeneratorRegistrationAttribute(typeof(FilePluralizationGenerator), nameof(FilePluralizationGenerator), VSConstants.UICONTEXT.CSharpProject_string, GeneratesDesignTimeSource = true)]
    [ProvideObject(typeof(FilePluralizationGenerator))]
    public sealed class FilePluralizationGenerator : IVsSingleFileGenerator

这里的 ProvideObject 是做注入使用的,添加这个特性将会注入到 VisualStudio 插件,但是如果有看过之前的博客,就会发现默认需要自己修改注册表的方法才能做到使用自定义工具,现在可以创建 CodeGeneratorRegistrationAttribute 这个类,继承 RegistrationAttribute 做到修改注册表,请看代码

代码语言:javascript
复制
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public sealed class CodeGeneratorRegistrationAttribute : RegistrationAttribute
    {
        public CodeGeneratorRegistrationAttribute(Type generatorType, string generatorName, string contextGuid)
        {
           
        }

        
        /// <summary> 
        ///     Called to register this attribute with the given context.  The context 
        ///     contains the location where the registration information should be placed. 
        ///     It also contains other information such as the type being registered and path information. 
        /// </summary> 
        public override void Register(RegistrationContext context)
        {
            // 写注册表
        }

        /// <summary> 
        /// Unregister this file extension. 
        /// </summary> 
        /// <param name="context"></param> 
        public override void Unregister(RegistrationContext context)
        {

        }
    }

此时在 FilePluralizationGenerator 上进行断点,然后运行插件,在调试的 VisualStudio 创建一个项目,添加一个 Foo.txt 文本,右击属性,修改自定义工具

此时就可以看到代码运行,输出的林德熙是逗比将会写入到 Foo.txt 下面的 Foo.generated.cs 文件里面

修改 Foo.txt 文件,点击保存会继续进入函数,在自定义工具可以在文件修改的时候自动调用

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档