![]() |
VOOZH | about |
dotnet add package Rougamo.Fody --version 5.0.2
NuGet\Install-Package Rougamo.Fody -Version 5.0.2
<PackageReference Include="Rougamo.Fody" Version="5.0.2" />
<PackageVersion Include="Rougamo.Fody" Version="5.0.2" />Directory.Packages.props
<PackageReference Include="Rougamo.Fody" />Project file
paket add Rougamo.Fody --version 5.0.2
#r "nuget: Rougamo.Fody, 5.0.2"
#:package Rougamo.Fody@5.0.2
#addin nuget:?package=Rougamo.Fody&version=5.0.2Install as a Cake Addin
#tool nuget:?package=Rougamo.Fody&version=5.0.2Install as a Cake Tool
中文 | English
Rougamo is a static code weaving AOP component. Commonly used AOP components include Castle, Autofac, and AspectCore. Unlike these components, which typically implement AOP through dynamic proxy and IoC mechanisms at runtime, Rougamo achieves AOP by directly modifying the target method's IL code during compilation. Rougamo supports all types of methods, including synchronous/asynchronous methods, static/instance methods, constructors, and properties.
Rougamo, a type of traditional Chinese street food, is somewhat similar to a hamburger, as both involve meat being sandwiched between bread. Every time I mention AOP, I think of Rougamo, because AOP is just like Rougamo, do aspects around the mehod.
Advantages:
Disadvantages: Larger Assembly Size, Since Rougamo is a compile-time AOP, it weaves additional code into the assembly at compile time, which increases the assembly size. However, this overhead is generally minimal and can be evaluated in your project through configuration options.
As an AOP component, Rougamo's primary function is to execute additional operations at key lifecycle points of a method. Rougamo supports four lifecycle points (or Join Points):
try..finally).Here's a simple example demonstrating how lifecycle points are expressed in code:
// Define a type inheriting from MoAttribute
public class TestAttribute : MoAttribute
{
public override void OnEntry(MethodContext context)
{
// OnEntry corresponds to before method execution
}
public override void OnException(MethodContext context)
{
// OnException corresponds to after method throws an exception
}
public override void OnSuccess(MethodContext context)
{
// OnSuccess corresponds to after method execution successfully
}
public override void OnExit(MethodContext context)
{
// OnExit corresponds to when method exits
}
}
At each lifecycle point, in addition to performing operations like logging, measuring method execution time, and APM instrumentation that don't affect method execution, you can also:
The simplest and most direct way is to apply the defined Attribute directly to methods. This can include synchronous and asynchronous methods, instance methods and static methods, properties and property getters/setters, as well as instance and static constructors:
class Abc
{
[Test]
static Abc() { }
[Test]
public Abc() { }
[Test]
public int X { get; set; }
public static Y
{
[Test]
get;
[Test]
set;
}
[Test]
public void M() { }
[Test]
public static async ValueTask MAsync() => await Task.Yield();
}
Applying attributes directly to methods is straightforward, but for common AOP types, adding the attribute to every method can be cumbersome. Rougamo also provides several bulk application methods:
When applying attributes in bulk, such as applying TestAttribute to a class, you typically don’t want every method in the class to receive TestAttribute. Instead, you may want to select methods that meet specific criteria. Rougamo offers two methods for method selection:
In modern development, asynchronous programming has become quite common. In the previous example, the method lifecycle nodes correspond to synchronous methods. If you need to perform asynchronous operations, you would have to manually block asynchronous operations to wait for the results, which can lead to resource wastage and performance loss. Rougamo provides asynchronous aspects in addition to synchronous aspects to better support asynchronous operations:
// Define a type that inherits from AsyncMoAttribute
public class TestAttribute : AsyncMoAttribute
{
public override async ValueTask OnEntryAsync(MethodContext context) { }
public override async ValueTask OnExceptionAsync(MethodContext context) { }
public override async ValueTask OnSuccessAsync(MethodContext context) { }
public override async ValueTask OnExitAsync(MethodContext context) { }
}
However, if asynchronous operations are not needed, it's still recommended to use synchronous aspects. For more information on asynchronous aspects, you can refer to Asynchronous Aspects.
Rougamo is a method-level AOP component. When applying Rougamo to methods, it instantiates related objects each time the method is called, which adds a burden to garbage collection (GC). Although this overhead is usually minimal and often negligible, Rougamo addresses performance impact by providing various optimization strategies:
Partial Weaving: If you only want to record a call log before method execution and do not need other lifecycle nodes or exception handling, you can use partial weaving to include only the required functionalities. This reduces the actual IL code woven and minimizes the number of instructions executed at runtime.
Structs: One difference between classes and structs is that classes are allocated on the heap, while structs are allocated on the stack. Using structs can allocate some Rougamo types on the stack, reducing GC pressure.
Slimming MethodContext: MethodContext holds contextual information about the current method. This information requires additional objects and involves boxing and unboxing operations, such as for method parameters and return values. If you do not need this information, slimming down MethodContext can achieve certain optimization effects.
Forced Synchronization: As discussed in Asynchronous Aspects, asynchronous aspects use ValueTask to optimize synchronous execution but still incur additional overhead. If asynchronous operations are not required, forcing synchronous aspects can avoid the extra costs of asynchronous aspects.
Custom Aspect Type Lifecycle, structs can avoid the creation of reference types, but they also have many limitations themselves, such as being unable to inherit from a parent class to reuse logic, unable to inherit from Attribute which results in an inability to specify parameters when applying aspect types (Attributes can specify constructor and property parameters when applied [Xyz(123, V = "abc")]). A way to balance usability and performance is through custom declaration cycles.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 is compatible. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 is compatible. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 is compatible. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 is compatible. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on Rougamo.Fody:
| Package | Downloads |
|---|---|
|
BotSharp.Core
Open source LLM application framework to build scalable, flexible and robust AI system. |
|
|
ThingsGateway.Admin.Application
Package Description |
|
|
ThingsGateway.Gateway.Application
Package Description |
|
|
HandeSoft.Core
Package Description |
|
|
HandeSoft.Web.Core
Package Description |
Showing the top 8 popular GitHub repositories that depend on Rougamo.Fody:
| Repository | Stars |
|---|---|
|
RayWangQvQ/BiliBiliToolPro
B 站(bilibili)自动任务工具,支持docker、青龙、k8s等多种部署方式。全面拥抱AI。敏感肌也能用。
|
|
|
dotnetcore/FreeSql
.NET aot orm, VB.NET/C# orm, Mysql/PostgreSQL/SqlServer/Oracle orm, Sqlite/Firebird/Clickhouse/DuckDB orm, 达梦/金仓/虚谷/翰高/高斯 orm, 神通 orm, 南大通用 orm, 国产 orm, TDengine orm, QuestDB orm, MsAccess orm.
|
|
|
SciSharp/BotSharp
AI Multi-Agent Framework in .NET
|
|
|
ThingsGateway/ThingsGateway
ThingsGateway is a cross-platform, high-performance gateway for edge data acquisition and IoT connectivity. Developed with .NET 8, it offers a suite of powerful tools, including advanced PLC communication libraries and debugging software.
|
|
|
mrtylerzhou/AntFlow.net
.net首个钉钉工作流UI风格BPM工作流平台!支持数十种数据库,开箱即用。同时也是一款纯血版工作流引擎,仅依赖了asp.net 9.0和freesql,natasha等几款优秀开源项目。致力解决传统工作流流程图必须由专业程序员绘制、学习曲线陡峭、上手难、排查问题难、维护成本高等问题。如果喜欢请给颗⭐️。
|
|
|
2881099/FreeSql.AdminLTE
这是一个 .NETCore MVC 中间件,基于 AdminLTE 前端框架动态产生 FreeSql 实体的增删查改界面。
|
|
|
hzy-6/hzy-admin
前后端分离权限管理系统基架! 数据权限、按钮权限、动态菜单、动态任务调度、动态WebApi、定时标记 [Scheduled("0/5 * * * * ?")] 、代码生成
|
|
|
netcorepal/d3shop
An online shop project based on Domain-Driven Design
|
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.2 | 130,192 | 10/13/2025 |
| 5.0.2-preview-1758270773 | 347 | 9/19/2025 |
| 5.0.1 | 108,551 | 6/22/2025 |
| 5.0.1-preview-1750248426 | 247 | 6/18/2025 |
| 5.0.0 | 165,592 | 12/8/2024 |
| 5.0.0-preview-1733564400 | 208 | 12/7/2024 |
| 5.0.0-preview-1733289406 | 205 | 12/4/2024 |
| 4.0.4 | 24,585 | 9/29/2024 |
| 4.0.4-preview-1727349912 | 231 | 9/26/2024 |
| 4.0.3 | 2,403 | 9/16/2024 |
| 4.0.3-preview-1726120802 | 242 | 9/12/2024 |
| 4.0.3-preview-1725957423 | 251 | 9/10/2024 |
| 4.0.2 | 907 | 9/9/2024 |
| 4.0.2-preview-1725956948 | 208 | 9/10/2024 |
| 4.0.2-preview-1725875652 | 250 | 9/9/2024 |
| 4.0.2-preview-1725466232 | 224 | 9/4/2024 |
| 4.0.1 | 4,200 | 9/2/2024 |
| 4.0.1-preview-1725141430 | 225 | 8/31/2024 |
| 4.0.0 | 12,994 | 8/10/2024 |
| 4.0.0-priview-1723306347 | 259 | 8/10/2024 |