当前位置:网站首页>Metalama简介4.使用Fabric操作项目或命名空间
Metalama简介4.使用Fabric操作项目或命名空间
2022-04-23 13:01:00 【重典】
Metalama中的Fabric可以做什么
Fabric通过修改项目、命名空间、类型来达到一些效果,这引起修改包括:添加Aspect或添加代码分析
使用Fabric为指定的方法添加Aspect
前文中我们写过一个简单的Aspect:
public class LogAttribute : OverrideMethodAspect
{
public override dynamic? OverrideMethod()
{
Console.WriteLine(meta.Target.Method.ToDisplayString() + " 开始运行.");
var result = meta.Proceed();
Console.WriteLine(meta.Target.Method.ToDisplayString() + " 结束运行.");
return result;
}
}
当我们使用它时,我们要在对应的方法上添加这个Attribute:
[Log]
private static int Add(int a, int b) //... ...
那么当我们有一个Aspect要在项目中大量使用时,在每个方法上添加这个Aspect当然是一种方法,但是这种方法有2个缺点:
- 包含大量的重复代码
[Log] - 对于原代码的入侵性太强
此时我们就可以使用Fabric为所有符合要求的方法添加指定的Aspect:
internal class Fabric : ProjectFabric
{
// 这个是重写项目的Fabric中修改项目的方法
public override void AmendProject(IProjectAmender amender)
{
// 添加 LogAttribute 到符合规则的方法上
// 为名为 Add 且 private 的方法添加 LogAttribute
amender.WithTargetMembers(c =>
c.Types.SelectMany(t => t.Methods)
.Where(t =>
t.Name == "Add" &&
t.Accessibility == Metalama.Framework.Code.Accessibility.Private)
).AddAspect(t => new LogAttribute());
}
}
这样就可以在不入侵现有代码的情况下为指定的方法添加Aspect。
使用Fabric添加代码分析
上文中我们提到,我们可以通过Aspect为代码添加代码分析,当我们要将一个包含(且仅包含)代码分析的Aspect应用于一批代码时,当然我们可以按本文示例1中的方法,直接使用Fabric将包含代码分析的Aspect应用于指定代码。
但还有另外一种方法,我们可以直接在Fabric中定义应用于指定代码的代码分析。
下面示例,我们验证所有类中的私有字段必须符合 _camelCase,并且使用一个NamespaceFabric来实现:
namespace FabricCamelCaseDemo;
class Fabric : NamespaceFabric
{
private static readonly DiagnosticDefinition<string> _warning = new(
"DEMO04",
Severity.Warning,
"'{0}'必须使用驼峰命名法并以'_'开头");
// 这个是命名空间的Fabric中修改命名空间规则 的方法
public override void AmendNamespace(INamespaceAmender amender)
{
// 取所有非static 的private的字段,并添加代码分析
amender.WithTargetMembers(c =>
c.AllTypes.SelectMany(t=>t.Fields)
.Where(t => t.Accessibility == Accessibility.Private && !t.IsStatic
)
)
//preview 0.5.8之前为 RegisterFinalValidator
.Validate(this.FinalValidator);
}
private void FinalValidator(in DeclarationValidationContext context)
{
var fullname = context.Declaration.ToDisplayString();
var fieldName = fullname.Split('.').LastOrDefault();
if (fieldName!=null && (!fieldName.StartsWith("_") || !char.IsLower(fieldName[1])))
{
context.Diagnostics.Report(_warning.WithArguments(fieldName));
}
}
}
当然因为当前使用的是NamespaceFabric所以该规则只应用于当前命名空间如,我们如果在另外一个命名空间中定义一个违反规则的字段的话,并不会有警告。
namespace FabricCamelCase;
internal class OtherNamespace
{
int count = 0;
int _total = 0;
public int Add()
{
count++;
_total++;
return count + _total;
}
}
使用TypeFabric为类型动态添加方法
开始前伪造一个需求,假设我有一个类AddUtils专门处理加法操作,它里面应该有从2个到15个参数的Add方法15个(当然我知道,可以使用params等方法实现,所以这里是个伪需求)。
最终效果为
public class AddUtils
{
public int Add2(int x1, int x2)
{
var result = 0;
result += x1;
result += x2;
return 2;
}
public int Add3(int x1, int x2, int x3)
{
var result = 0;
result += x1;
result += x2;
result += x3;
return 3;
}
// 以此类推... 下面省去若干方法
}
那么我们可以用Metalama如此实现
using System.Reflection.Emit;
using Metalama.Framework.Aspects;
using Metalama.Framework.Fabrics;
public class AddUtils
{
private class Fabric : TypeFabric
{
// 实现的方法体
[Template]
public int MethodTemplate()
{
var num = (int) meta.Tags["nums"]!;
var result = 0;
foreach (var targetParameter in meta.Target.Parameters)
{
result += targetParameter.Value;
}
return num;
}
public override void AmendType(ITypeAmender amender)
{
for (var i = 2; i < 15; i++)
{
// 生成一个方法
var methodBuilder = amender.Advices.IntroduceMethod(
amender.Type,
nameof(this.MethodTemplate),
tags: new TagDictionary { ["nums"] = i });
// 方法名
methodBuilder.Name = "Add" + i;
// 添加参数
for (int parameterIndex = 1; parameterIndex <= i; parameterIndex++)
{
methodBuilder.AddParameter($"x{parameterIndex}", typeof(int));
}
}
}
}
}
引用
本章源代码:https://github.com/chsword/metalama-demo
Metalama官方文档: https://doc.metalama.net/
Metalama Nuget包: https://www.nuget.org/packages/Metalama.Framework/0.5.11-preview
版权声明
本文为[重典]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/1986099
边栏推荐
- Unlock openharmony technology day! The annual event is about to open!
- Go iris framework implements multi service Demo: start (listen to port 8084) service 2 through the interface in service 1 (listen to port 8083)
- The continuous construction of the Internet industry platform is not only able to collect traffic
- 内核错误: No rule to make target ‘debian/canonical-certs.pem‘, needed by ‘certs/x509_certificate_list‘
- Keyword interpretation and some APIs in RT thread
- Go language: passing slices between functions
- STD:: shared of smart pointer_ ptr、std::unique_ ptr
- R语言中dcast 和 melt的使用 简单易懂
- 31. Next arrangement
- async void 导致程序崩溃
猜你喜欢

8086 of x86 architecture

云原生KubeSphere部署Redis

内核错误: No rule to make target ‘debian/canonical-certs.pem‘, needed by ‘certs/x509_certificate_list‘

CGC: contractual graph clustering for community detection and tracking

Wonderful review | the sixth issue of "source" - open source economy and industrial investment

Complete project data of UAV apriltag dynamic tracking landing based on openmv (LabVIEW + openmv + apriltag + punctual atom four axes)

Softbank vision fund entered the Web3 security industry and led a new round of investment of US $60 million in certik

Read the data in Presto through sparksql and save it to Clickhouse

教你快速开发一个 狼人杀微信小程序(附源码)

8 websites that should be known for product development to enhance work experience
随机推荐
V-model binding value in El select, data echo only displays value, not label
JDBC connection pool
【蓝桥杯】4月17日省赛刷题训练(前3道题)
Wu Enda's programming assignment - logistic regression with a neural network mindset
HQL statement tuning
Free and open source intelligent charging pile SaaS cloud platform of Internet of things
Fashion cloud learning - input attribute summary
The continuous construction of the Internet industry platform is not only able to collect traffic
MySQL supports IP access
Remote sensing image classification and recognition system based on convolutional neural network
Object.keys后key值数组乱序的问题
ZigBee CC2530 minimum system and register configuration (1)
Important knowledge of transport layer (interview, retest, final)
21 days learning mongodb notes
[Blue Bridge Cup] April 17 provincial competition brushing training (the first three questions)
Golang implements a five insurance and one gold calculator with web interface
Unable to create servlet under SRC subfile of idea
[vulnhub range] - DC2
SSM framework series - JUnit unit test optimization day2-3
Go language slicing operation