使用它们可以快速进行一些快捷的针对代码的操作,如提取接口、添加实现、自动属性、快速重构、删除引用等。
除官方提供的功能外我们还可以使用很多第三方插件来支持更多地功能。
可以通过编写代码的形式,让我们为指定的代码添加或的功能。
自定义一个ToString的实时模板
很多图形编程或游戏编程中,我们会用到各种自定义类如矩阵、复数、坐标系等,为了方便Debug,我们通常会为这些类增加一个方法的重写。
例如
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}";
}
}
如果我们不想手写这个方法,而想让VS直接为它生成。
则我们可以使用定义一个LiveTemplate,这样就可以在VS的工具中使用它了。
[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(;
}
}
这样在,下列代码中使用功能,即可看到给的实时代码提示。
internal class Point
{
public double X;
public double Y;
}
使用Metalama添加一个VisualStudio的快速操作
这需要我们在中添加一个提示:
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]
internal class Point // 在此处触发 Ctrl+.或右键
{
public double X;
public double Y;
}
引用
本章源代码:https://github.com/chsword/metalama-demo