ModInteropImportGenerator 1.1.0

dotnet add package ModInteropImportGenerator --version 1.1.0
                    
NuGet\Install-Package ModInteropImportGenerator -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ModInteropImportGenerator" Version="1.1.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ModInteropImportGenerator" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ModInteropImportGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ModInteropImportGenerator --version 1.1.0
                    
#r "nuget: ModInteropImportGenerator, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ModInteropImportGenerator@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ModInteropImportGenerator&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ModInteropImportGenerator&version=1.1.0
                    
Install as a Cake Tool

ModInteropImportGenerator

Generates MonoMod.ModInterop imports based on a given method signature and name.

Terminology

Term Definition
Dependency An assembly that includes one or more export classes.
Export class A class annotated with [ModExportName] that contains one or more export methods.
Export name The name passed to the [ModExportName] annotation.
Export method A public static method inside an export class.
Import class A class annotated with [GenerateImports] that contains one or more import methods.
Import name The name passed to the [GenerateImports] annotation.
Import method A public static partial method inside an import class that does not have a method body.
Import The process of assigning the correct export method implementation to import methods of a given import class, based on the import name as well as the import method name and signature.

Demonstration

Assume the following export class:

[ModExportName("CommunalHelper.DashStates")]
public static class DashStates
{
    #region DreamTunnel

    public static int GetDreamTunnelDashState()
    {
        return St.DreamTunnelDash;
    }

    public static bool HasDreamTunnelDash()
    {
        return DreamTunnelDash.DreamTunnelDashCount > 0;
    }

    public static int GetDreamTunnelDashCount()
    {
        return DreamTunnelDash.DreamTunnelDashCount;
    }

    public static Component DreamTunnelInteraction(
        Action<Player> onPlayerEnter,
        Action<Player> onPlayerExit)
    {
        return new DreamTunnelInteraction(onPlayerEnter, onPlayerExit);
    }

    #endregion

    #region Seeker

    public static bool HasSeekerDash()
    {
        return SeekerDash.HasSeekerDash;
    }

    public static bool IsSeekerDashAttacking()
    {
        return SeekerDash.SeekerAttacking;
    }

    #endregion
}

Normally, to import it, you would define your import class like so, and call typeof(DashStates).ModInterop();:

[ModImportName("CommunalHelper.DashStates")]
public static class DashStates
{
    public static Func<int> GetDreamTunnelDashState;
    public static Func<bool> HasDreamTunnelDash;
    public static Func<int> GetTunnelDashCount;
    public static Func<Action<Player>, Action<Player>, Component>
        DreamTunnelInteraction;
    public static Func<bool> HasSeekerDash;
    public static Func<bool> IsSeekerDashAttacking;
}

This form can be confusing for new code modders and may sometimes be difficult to read.

However, with this source generator you can now copy-paste the method signatures and mark them as partial! The source generator will figure out the rest.

[GenerateImports("CommunalHelper.DashStates")]
public static partial class DashStates
{
    public static partial int GetDreamTunnelDashState();
    public static partial bool HasDreamTunnelDash();
    public static partial int GetDreamTunnelDashCount();
    public static partial Component DreamTunnelInteraction(
        Action<Player> onPlayerEnter, Action<Player> onPlayerExit);
    public static partial bool HasSeekerDash();
    public static partial bool IsSeekerDashAttacking();
}
  • The definition is more readable (literally just a function)
  • You don't have to convert function signatures into Func<...>s or Action<...>s, or define your own delegate types
  • You get parameter names as a bonus
  • You don't have to constantly slap an ?.Invoke(...) on the imported methods if the dependency is optional

Referencing

Add the ModInteropImportGenerator NuGet package to your csproj like so:

<ItemGroup>
    <PackageReference Include="ModInteropImportGenerator" Version="*" />
</ItemGroup>

Usage

Importing methods is done in a very similar fashion to how it was previously done with [ModImportName] and typeof(...).ModInterop();.

Define a public static partial class and give it the [GenerateImports] attribute. Make sure the import name matches the export name you're interested in.

// DashStates.cs

using MonoModImportGenerator;

[GenerateImports("CommunalHelper.DashStates")]
public static partial class DashStates
{
}

Next, define import methods that have the same name and signature as the export methods that you're interested in.
The easiest way would be to copy-paste the export method definitions, leave out the method bodies and mark them as partial (and of course add the semicolon at the end).

// DashStates.cs

using MonoModImportGenerator;

[GenerateImports("CommunalHelper.DashStates")]
public static partial class DashStates
{
    public static partial int GetDreamTunnelDashState();
    public static partial bool HasDreamTunnelDash();
    public static partial int GetDreamTunnelDashCount();
    public static partial Component DreamTunnelInteraction(
        Action<Player> onPlayerEnter, Action<Player> onPlayerExit);
    public static partial bool HasSeekerDash();
    public static partial bool IsSeekerDashAttacking();
}

Finally, call the Load() method on the import class. This method is automatically generated by the source generator.

// YourModModule.cs

public override void Load()
{
    DashStates.Load();
    
    // ...
}

You may now call the import methods.
By default, the source generator will treat the import class as an optional dependency. If the dependency is not present at the time Load() is called, the import methods will throw an exception when called.

To safely call an import method, you must check if the IsImported bool property is true.

if (DashStates.IsImported)
    DashStates.GetDreamTunnelDashState();

You can tell the source generator to treat the import class as a required dependency by setting the RequiredDependency property to true. This will throw an exception directly in Load() if any methods fail to import.

// DashStates.cs

using MonoModImportGenerator;

[GenerateImports("CommunalHelper.DashStates", RequiredDependency = true)]
public static partial class DashStates
{
    // ...
}

You can see the state of the import in the ImportState property of the import class.

Building

Clone the project and build the ModInteropImportGenerator project. Prefer Release mode as it's more optimized.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 135 9/2/2025
1.0.0 129 9/2/2025

- Deprecated DependencyNotPresent in favor of the new ImportFailed ImportState enum
           - Replaced the UnreachableException with InvalidOperationException if the import state is invalid
           - Adjusted exception messages