Skip to content

Commit

Permalink
Update readme.
Browse files Browse the repository at this point in the history
  • Loading branch information
inversionhourglass committed Oct 15, 2024
1 parent 9c47913 commit 995be48
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 12 deletions.
67 changes: 61 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ Cli4Fody是一个命令行工具,用于管理Fody插件和修改`FodyWeavers.x

执行如下命令:

> fody-cli MySolution.sln --addin ConfigureAwait -a ContinueOnCapturedContext=true
> fody-cli MySolution.sln --addin ConfigureAwait -a ContinueOnCapturedContext=false --addin Rougamo
执行命令后的`FodyWeavers.xml`

```xml
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="true" />
<ConfigureAwait ContinueOnCapturedContext="false" />
<Rougamo />
</Weavers>
```

Expand All @@ -36,6 +37,10 @@ Cli4Fody是一个命令行工具,用于管理Fody插件和修改`FodyWeavers.x
- `<solutionOrProjectPath>` 解决方案文件(*.sln)路径或项目文件(*.csproj)路径
- Options
- `--include-fody <VERSION>`

增加Fody NuGet依赖,`<VERSION>`为Fody的版本号。

- `--share <project|solution>`

`FodyWeavers.xml`文件共享设置,默认`project`,为每个项目创建一个`FodyWeavers.xml`,设置为`solution`时仅在解决方案目录创建`FodyWeavers.xml`文件,当`<solutionOrProjectPath>`为项目文件路径时,该配置无效。
Expand Down Expand Up @@ -76,15 +81,15 @@ Cli4Fody是一个命令行工具,用于管理Fody插件和修改`FodyWeavers.x

- `-pv, --package-version`

插件版本,`--addin`的子配置项。当指定该参数后,Cli4Fody会为每个项目添加当前插件的NuGet,版本为当前参数值。该参数可以用来解决Fody插件间接依赖MSBuild任务无效的问题,该参数为每个项目添加NuGet直接依赖。需要注意的是,为了加快Cli4Fody的执行速度,NuGet采用了`--no-restore`的方式进行安装。
插件版本,`--addin`的子配置项。当指定该参数后,Cli4Fody会为每个项目添加当前插件的NuGet依赖,版本为当前参数值。该参数可以用来解决Fody插件间接依赖MSBuild任务无效的问题,该参数为每个项目添加NuGet直接依赖。需要注意的是,为了加快Cli4Fody的执行速度,NuGet采用了`--no-restore`的方式进行安装。

- `-m, --mode <overwrite|default>`

操作模式,`--addin`的子配置项,默认`overwrite`,新建或重写以存在的`--addin`配置节点;`default`表示仅作为默认配置,如果`--addin`配置节点已存在则不进行任何修改。注意`-m, --mode`作为`--addin`的子配置项,必须在`--addin`之后指定。

正确用法:`fody-cli MySolution.sln --addin Rougamo -m default`

错误用法:`fody-cli MySolution.sln -m default --addin Rougamo`

正确用法:`fody-cli MySolution.sln --addin Rougamo -m default`

- `-n, --node <NODE>`

Expand Down Expand Up @@ -133,6 +138,56 @@ Cli4Fody是一个命令行工具,用于管理Fody插件和修改`FodyWeavers.x
</Weavers>
```

## 零侵入代码织入案例
## 使用场景

Cli4Fody主要有两个应用场景:
1. 你平时在使用Fody插件的时候可能已经发现,自己的项目必须直接依赖Fody插件,间接依赖时Fody插件不生效,比如[项目A] -> [项目B] -> Rougamo.Fody,此时项目A中是可以使用Rougamo.Fody中定义的类型的,但在编译时并没有修改对应的MSIL,必须项目A直接依赖Rougamo.Fody才会生效。出现这种情况是因为Fody调用系列插件修改MSIL是通过在MSBuild管道中插入一个在编译后执行的任务实现的,Fody的NuGet包中的build目录下包含了添加MSBuild任务的配置。而在项目依赖中,默认是不会传递这些配置的,所以需要每个项目都直接依赖Fody插件。

由于间接依赖时已经能够使用到Fody插件中的类型,所以我们很容易忘记直接依赖Fody插件,导致最终插件未生效,此时便可以通过Cli4Fody为解决方案中的每个项目添加直接依赖。下面的命令会为解决方案的每个项目添加Rougamo.Fody的直接依赖,并新增/修改FodyWeavers.xml文件。
> fody-cli MySolution.sln --addin Rougamo -pv 4.0.4

2. 部分Fody插件是可以仅通过配置来完成其目标的,比如ConfigureAwait.Fody、Pooling.Fody等。对于这类插件,可以通过Cli4Fody直接完成配置。

```shell
fody-cli MySolution.sln \
--addin ConfigureAwait -pv 3.3.2 -a ContinueOnCapturedContext=false \
--addin Pooling -pv 0.1.0 \
-n Inspects:Inspect -v "execution(* *..*Serivce.*(..))" \
-n Items:Item -a stateless=Random
```

### 推荐实践

Cli4Fody非常适配CI,可以在自动构建中统一配置,既可以轻松的完成对Fody插件直接依赖的查漏补缺,也可以轻松地配置无侵入式Fody插件。比如可以参考[DockerSample](https://github.com/inversionhourglass/Cli4Fody/tree/master/samples/DockerSample)项目,在Dockerfile中通过Cli4Fody确保Rougamo.Fody的直接依赖以及添加对ConfigureAwait的依赖并进行配置。

```docker
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
USER app
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src

COPY ["ConsoleApp/ConsoleApp.csproj", "ConsoleApp/"]
RUN dotnet restore "./ConsoleApp/ConsoleApp.csproj"

COPY . .

ENV PATH="$PATH:/root/.dotnet/tools"
RUN dotnet tool install -g Cli4Fody
RUN fody-cli DockerSample.sln --addin Rougamo -pv 4.0.4 --addin ConfigureAwait -pv 3.3.2 -a ContinueOnCapturedContext=false

RUN dotnet restore "./ConsoleApp/ConsoleApp.csproj"

RUN dotnet publish "./ConsoleApp/ConsoleApp.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ConsoleApp.dll"]
```

### Pooling零侵入实践

[Pooling](https://github.com/inversionhourglass/Pooling) 使用 Cli4Fody 实现[零侵入式对象池操作替换](https://github.com/inversionhourglass/Pooling?tab=readme-ov-file#%E9%9B%B6%E4%BE%B5%E5%85%A5%E5%BC%8F%E6%B1%A0%E5%8C%96%E6%93%8D%E4%BD%9C)
74 changes: 68 additions & 6 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ Assume the current solution `MySolution.sln` has the following `FodyWeavers.xml`

Execute the following command:

> fody-cli MySolution.sln --addin ConfigureAwait -a ContinueOnCapturedContext=true
> fody-cli MySolution.sln --addin ConfigureAwait -a ContinueOnCapturedContext=false --addin Rougamo
The `FodyWeavers.xml` after executing the command:

```xml
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="true" />
<ConfigureAwait ContinueOnCapturedContext="false" />
<Rougamo />
</Weavers>
```

Expand All @@ -36,6 +37,10 @@ The `FodyWeavers.xml` after executing the command:
- `<solutionOrProjectPath>` The path to the solution file (*.sln) or project file (*.csproj).
- Options
- `--include-fody <VERSION>`

Add Fody NuGet dependency, with `<VERSION>` being the version number of Fody.

- `--share <project|solution>`

Specifies the sharing setting for the `FodyWeavers.xml` file. The default is `project`, which creates a separate `FodyWeavers.xml` for each project. Setting it to `solution` will create only one `FodyWeavers.xml` file in the solution directory. This configuration is ineffective when `<solutionOrProjectPath>` is the path to a project file.
Expand Down Expand Up @@ -76,15 +81,15 @@ The `FodyWeavers.xml` after executing the command:

- `-pv, --package-version`

Plugin version, a sub-option of `--addin`. When this parameter is specified, Cli4Fody will add the NuGet package of the current plugin to each project, with the version being the current parameter value. This parameter can be used to resolve issues where indirect dependencies on MSBuild tasks by Fody plugins are ineffective. By adding a direct NuGet dependency to each project, this issue can be mitigated. It's important to note that to speed up the execution of Cli4Fody, NuGet packages are installed using the `--no-restore` option.
Plugin version, a sub-option of `--addin`. When this parameter is specified, Cli4Fody will add the NuGet package dependency of the current plugin to each project, with the version being the current parameter value. This parameter can be used to resolve issues where indirect dependencies on MSBuild tasks by Fody plugins are ineffective. By adding a direct NuGet dependency to each project, this issue can be mitigated. It's important to note that to speed up the execution of Cli4Fody, NuGet packages are installed using the `--no-restore` option.

- `-m, --mode <overwrite|default>`

Operation mode, a sub-option of `--addin`. The default is `overwrite`, which creates or overwrites an existing `--addin` configuration node. `default` means to set it as the default configuration; if the `--addin` configuration node already exists, no changes are made. Note that `-m, --mode` must be specified after `--addin` as a sub-option of `--addin`.

Correct usage: `fody-cli MySolution.sln --addin Rougamo -m default`

Incorrect usage: `fody-cli MySolution.sln -m default --addin Rougamo`

Correct usage: `fody-cli MySolution.sln --addin Rougamo -m default`

- `-n, --node <NODE>`

Expand Down Expand Up @@ -133,6 +138,63 @@ The `FodyWeavers.xml` after executing the command:
</Weavers>
```

## Non-Intrusive Code Weaving Case
## Usage Scenarios

Cli4Fody has two primary use cases:

1. **Direct Dependency on Fody Plugins**:
You may have noticed that when using Fody plugins, your project must directly depend on them. Indirect dependencies don’t work. For example, in the dependency chain [Project A] → [Project B] → Rougamo.Fody, Project A can use the types defined in Rougamo.Fody, but the corresponding MSIL (Microsoft Intermediate Language) won’t be modified unless Project A directly depends on Rougamo.Fody. This is because Fody modifies the MSIL through tasks inserted into the MSBuild pipeline after compilation, and these tasks are included in the Fody NuGet package under the `build` directory. In an indirect dependency scenario, the build configuration won’t be transmitted automatically, so each project needs to directly depend on the Fody plugin.

Since Fody plugin types can be used indirectly, it’s easy to forget to directly add the dependency, causing the plugin to not function properly. With Cli4Fody, you can resolve this issue by adding the direct dependency to every project in the solution. The following command will add a direct dependency on Rougamo.Fody to every project in the solution and create or update the `FodyWeavers.xml` file.

```
fody-cli MySolution.sln --addin Rougamo -pv 4.0.4
```

2. **Configuration-Only Plugins**:
Some Fody plugins, like ConfigureAwait.Fody and Pooling.Fody, can achieve their objectives through configuration alone. For these types of plugins, you can use Cli4Fody to directly configure them.

Example command:
```shell
fody-cli MySolution.sln \
--addin ConfigureAwait -pv 3.3.2 -a ContinueOnCapturedContext=false \
--addin Pooling -pv 0.1.0 \
-n Inspects:Inspect -v "execution(* *..*Service.*(..))" \
-n Items:Item -a stateless=Random
```

### Recommended Practices

Cli4Fody is well-suited for continuous integration (CI). You can easily configure it in an automated build process, ensuring both Fody plugin direct dependencies and non-invasive plugin configurations are applied consistently. For example, refer to the [DockerSample](https://github.com/inversionhourglass/Cli4Fody/tree/master/samples/DockerSample) project, where a Dockerfile uses Cli4Fody to ensure a direct dependency on Rougamo.Fody and add ConfigureAwait configuration.

```docker
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
USER app
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src

COPY ["ConsoleApp/ConsoleApp.csproj", "ConsoleApp/"]
RUN dotnet restore "./ConsoleApp/ConsoleApp.csproj"

COPY . .

ENV PATH="$PATH:/root/.dotnet/tools"
RUN dotnet tool install -g Cli4Fody
RUN fody-cli DockerSample.sln --addin Rougamo -pv 4.0.4 --addin ConfigureAwait -pv 3.3.2 -a ContinueOnCapturedContext=false

RUN dotnet restore "./ConsoleApp/ConsoleApp.csproj"

RUN dotnet publish "./ConsoleApp/ConsoleApp.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ConsoleApp.dll"]
```

## Pooling Zero-Intrusive Practice

[Pooling](https://github.com/inversionhourglass/Pooling) uses Cli4Fody to achieve [non-intrusive object pooling operation replacement](https://github.com/inversionhourglass/Pooling/blob/master/README_en.md#zero-intrusion-pooling).

0 comments on commit 995be48

Please sign in to comment.