前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Metalama简介5.配合VisualStudio自定义重构或快速操作功能

Metalama简介5.配合VisualStudio自定义重构或快速操作功能

作者头像
重典
发布2022-05-02 10:17:21
3620
发布2022-05-02 10:17:21
举报
文章被收录于专栏:重典.NET重典.NET

使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题

Metalama简介1. 不止是一个.NET跨平台的编译时AOP框架

Metalama简介2.利用Aspect在编译时进行消除重复代码

Metalama简介3.自定义.NET项目中的代码分析

Metalama简介4.使用Fabric操作项目或命名空间

Visual Studio中有提供快速操作(小灯泡)功能

以及重构(小刷子)功能

使用它们可以快速进行一些快捷的针对代码的操作,如提取接口、添加实现、自动属性、快速重构、删除引用等。

除官方提供的功能外我们还可以使用很多第三方插件来支持更多地功能。

Metalama可以通过编写代码的形式,让我们为指定的代码添加重构快速操作的功能。

自定义一个ToString的实时模板

很多图形编程或游戏编程中,我们会用到各种自定义类如矩阵、复数、坐标系等,为了方便Debug,我们通常会为这些类增加一个ToString方法的重写。

例如

代码语言:javascript
复制
internal class Program
{
    private static void Main()
    {
        var point = new Point { X = 5, Y = 3};
        Console.WriteLine($"point = {point}");
    }
}
internal class Point
{
    public double X;
    public double Y;
    public override string ToString()
    {
        return $"({X}, {Y})";
    }
}

如果我们不想手写这个ToString方法,而想让VS直接为它生成。

则我们可以使用Metalama定义一个LiveTemplate,这样就可以在VS的工具中使用它了。

代码语言:javascript
复制
[LiveTemplate] // 表示当前Aspect为VS添加LiveTempate
internal class ToStringAttribute : TypeAspect
{
    [Introduce(WhenExists = OverrideStrategy.Override, Name = "ToString")]
    public string IntroducedToString()
    {
        var stringBuilder = new InterpolatedStringBuilder();
        stringBuilder.AddText("{ ");
        stringBuilder.AddText(meta.Target.Type.Name);
        stringBuilder.AddText(" ");

        var fields = meta.Target.Type.FieldsAndProperties.Where(f => !f.IsStatic).ToList();

        var i = meta.CompileTime(0);

        foreach (var field in fields)
        {
            if (i > 0)
            {
                stringBuilder.AddText(", ");
            }

            stringBuilder.AddText(field.Name);
            stringBuilder.AddText("=");
            stringBuilder.AddExpression(field.Invokers.Final.GetValue(meta.This));

            i++;
        }

        stringBuilder.AddText(" }");

        return stringBuilder.ToValue();
    }
}

这样在,下列代码中使用重构功能,即可看到Metalama给的实时代码提示。

代码语言:javascript
复制
internal class Point
{
    public double X;
    public double Y;
}

使用Metalama添加一个VisualStudio的快速操作

我们最终的目的如下,对于标注了[Tostring]的类,增加一个将[ToString]切换至手动实现的功能点击后可实现自动添加一个ToString:

这需要我们在Aspect``ToStringAttribute中添加一个提示:

代码语言:javascript
复制
public class ToStringAttribute : TypeAspect
{
    public override void BuildAspect(IAspectBuilder<INamedType> builder)
    {
        base.BuildAspect(builder);
        // 添加一个建议手动实现的重构提示
        if (builder.AspectInstance.Predecessors[0].Instance is IAttribute attribute)
        {
            builder.Diagnostics.Suggest(
                new CodeFix("将 [ToString] 切换至手动实现", codeFixBuilder => this.ImplementManually(codeFixBuilder, builder.Target)),
                builder.Target);
        }
    }

    /// <summary>
    /// 当点击手动实现时的操作
    /// </summary>
    private async Task ImplementManually(ICodeActionBuilder builder, INamedType targetType)
    {
        await builder.ApplyAspectAsync(targetType, this);
        await builder.RemoveAttributesAsync(targetType, typeof(ToStringAttribute));
    }

    [Introduce(WhenExists = OverrideStrategy.Override, Name = "ToString")]
    public string IntroducedToString()
    {
        // 获取非静态字段
        var fields = meta.Target.Type.FieldsAndProperties.Where(f => !f.IsStatic).ToList();

        // 构建一个$""字符串
        var stringBuilder = new InterpolatedStringBuilder();
        stringBuilder.AddText("{ ");
        stringBuilder.AddText(meta.Target.Type.Name);
        stringBuilder.AddText(" ");

        var i = meta.CompileTime(0);

        foreach (var field in fields)
        {
            if (i > 0)
            {
                stringBuilder.AddText(", ");
            }

            stringBuilder.AddText(field.Name);
            stringBuilder.AddText("=");
            stringBuilder.AddExpression(field.Invokers.Final.GetValue(meta.This));

            i++;
        }

        stringBuilder.AddText(" }");
        return stringBuilder.ToValue();
    }
}

这样就可以对于已经添加了[ToString]的类实现以上功能

代码语言:javascript
复制
[ToString]
internal class Point // 在此处触发 Ctrl+.或右键
{
    public double X;
    public double Y;
}

引用

本章源代码:https://github.com/chsword/metalama-demo

Metalama官方文档: https://doc.metalama.net/

Metalama Nuget包: https://www.nuget.org/packages/Metalama.Framework/0.5.13-preview

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义一个ToString的实时模板
  • 使用Metalama添加一个VisualStudio的快速操作
  • 引用
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档