Skip to content

This is a simple solution built as a starter for writing Fody addins.

License

Notifications You must be signed in to change notification settings

robinzevallos/BasicFodyAddin

 
 

Repository files navigation

Chat on Gitter NuGet Status

Icon

This is a simple solution built as a starter for writing Fody addins.

Usage

See also Fody usage.

NuGet installation

Install the BasicFodyAddin.Fody NuGet package and update the Fody NuGet package:

PM> Install-Package Fody
PM> Install-Package BasicFodyAddin.Fody

The Install-Package Fody is required since NuGet always defaults to the oldest, and most buggy, version of any dependency.

Add to FodyWeavers.xml

Add <BasicFodyAddin/> to FodyWeavers.xml

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <BasicFodyAddin/>
</Weavers>

The moving parts

BasicFodyAddin Project

A project that contains all classes used for compile time metadata. Generally any usage and reference to this project is removed at compile time so it is not needed as part of application deployment.

This project is also used to produce the NuGet package. To achieve this the project consumes two NuGets:

  • Fody with PrivateAssets="None". This results in producing NuGet package having a dependency on Fody with all include="All" in the nuspec. Note that while this project consumes the Fody NuGet, weaving is not performed on this project. This is due to the FodyPackaging NuGet (see below) including <DisableFody>true</DisableFody> in the MSBuild pipeline.
  • FodyPackaging with PrivateAssets="All". This results in a NuGet package being produced by this project, but no dependency on FodyPackaging in the resulting NuGet package.

The produced NuGet package will be named with .Fody suffix.

This project should also contain all appropriate NuGet metadata properties. Many of these properties have defaults in FodyPackaging, but can be overriden.

The resultant NuGet package will target the same frameworks that this project targets.

The resultant NuGet package will be created in a diretory named nugets at the root of the solution.

BasicFodyAddin.Fody Project

The project that does the weaving.

This project has a NuGet dependency on FodyHelpers.

Target Frameworks

This project must target and netstandard2.0 (for .NET Framework net46 or above) so that it can target msbuild.exe or dotnet build.

Output of the project

It outputs a file named BasicFodyAddin.Fody. The '.Fody' suffix is necessary to be picked up by Fody at compile time.

ModuleWeaver

ModuleWeaver.cs is where the target assembly is modified. Fody will pick up this type during its processing. Note that the class must be named as ModuleWeaver.

ModuleWeaver has a base class of BaseModuleWeaver which exists in the FodyHelpers NuGet.

BaseModuleWeaver.Execute

Called to perform the manipulation of the module. The current module can be accessed and manipulated via BaseModuleWeaver.ModuleDefinition.

BaseModuleWeaver.GetAssembliesForScanning

Called by Fody when it is building up a type cache for lookups. This method should return all possible assemblies that the weaver may require while resolving types. In this case BasicFodyAddin requires System.Object, so GetAssembliesForScanning returns netstandard and mscorlib. It is safe to return assembly names that are not used by the current target assembly as these will be ignored.

To use this type cache, a ModuleWeaver can call BaseModuleWeaver.FindType within Execute method. For example in this project the following is called:

var objectRef = ModuleDefinition.ImportReference(FindType("System.Object"));
BaseModuleWeaver.ShouldCleanReference

When BasicFodyAddin.dll is referenced by a consuming project, it is only for the purposes configuring the weaving via attributes. As such, it is not required at runtime. With this in mind BaseModuleWeaver has an opt in feature to remove the reference, meaning the target weaved application does not need BasicFodyAddin.dll at runtime. This feature can be opted in to via the following code in ModuleWeaver:

public override bool ShouldCleanReference => true;
Other BaseModuleWeaver Members

BaseModuleWeaver has a number of other members for logging and extensibility:
https://github.com/Fody/Fody/blob/master/FodyHelpers/BaseModuleWeaver.cs

Resultant injected code

In this case a new type is being injected into the target assembly that looks like this.

public class Hello
{
    public string World()
    {
        return "Hello World";
    }
}

See ModuleWeaver for more details.

AssemblyToProcess Project

A target assembly to process and then validate with unit tests.

Tests Project

Contains all tests for the weaver.

The project has a NuGet dependency on FodyHelpers .

It has a reference to the AssemblyToProcess project, so that AssemblyToProcess.dll is copied to the bin directory of the test project.

FodyHelpers contains a utility WeaverTestHelper for executing test runs on a target assembly using a ModuleWeaver.

A test can then be run as follows:

public class WeaverTests
{
    static TestResult testResult;

    static WeaverTests()
    {
        var weavingTask = new ModuleWeaver();
        testResult = weavingTask.ExecuteTestRun("AssemblyToProcess.dll");
    }

    [Fact]
    public void ValidateHelloWorldIsInjected()
    {
        var type = testResult.Assembly.GetType("TheNamespace.Hello");
        var instance = (dynamic)Activator.CreateInstance(type);

        Assert.Equal("Hello World", instance.World());
    }
}

By default ExecuteTestRun will perform a PeVerify on the resultant assembly

Icon

Lego designed by Timur Zima from The Noun Project

About

This is a simple solution built as a starter for writing Fody addins.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%