Generates MonoMod.ModInterop imports based on a given method signature and name.
| 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. |
Assume the following export class:
[ModExportName("CommunalHelper.DashStates")]publicstaticclassDashStates{
#region DreamTunnel
publicstaticintGetDreamTunnelDashState(){returnSt.DreamTunnelDash;}publicstaticboolHasDreamTunnelDash(){returnDreamTunnelDash.DreamTunnelDashCount>0;}publicstaticintGetDreamTunnelDashCount(){returnDreamTunnelDash.DreamTunnelDashCount;}publicstaticComponentDreamTunnelInteraction(Action<Player>onPlayerEnter,Action<Player>onPlayerExit){returnnewDreamTunnelInteraction(onPlayerEnter,onPlayerExit);}
#endregion
#region Seeker
publicstaticboolHasSeekerDash(){returnSeekerDash.HasSeekerDash;}publicstaticboolIsSeekerDashAttacking(){returnSeekerDash.SeekerAttacking;}
#endregion
}Normally, to import it, you would define your import class like so, and call typeof(DashStates).ModInterop();:
[ModImportName("CommunalHelper.DashStates")]publicstaticclassDashStates{publicstaticFunc<int>GetDreamTunnelDashState;publicstaticFunc<bool>HasDreamTunnelDash;publicstaticFunc<int>GetTunnelDashCount;publicstaticFunc<Action<Player>,Action<Player>,Component>DreamTunnelInteraction;publicstaticFunc<bool>HasSeekerDash;publicstaticFunc<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")]publicstaticpartialclassDashStates{publicstaticpartialintGetDreamTunnelDashState();publicstaticpartialboolHasDreamTunnelDash();publicstaticpartialintGetDreamTunnelDashCount();publicstaticpartialComponentDreamTunnelInteraction(Action<Player>onPlayerEnter,Action<Player>onPlayerExit);publicstaticpartialboolHasSeekerDash();publicstaticpartialboolIsSeekerDashAttacking();}- The definition is more readable (literally just a function)
- You don't have to convert function signatures into
Func<...>s orAction<...>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
Add the ModInteropImportGenerator NuGet package to your csproj like so:
<ItemGroup>
<PackageReferenceInclude="ModInteropImportGenerator"Version="*" />
</ItemGroup>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.csusingModInteropImportGenerator;[GenerateImports("CommunalHelper.DashStates")]publicstaticpartialclassDashStates{}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.csusingModInteropImportGenerator;[GenerateImports("CommunalHelper.DashStates")]publicstaticpartialclassDashStates{publicstaticpartialintGetDreamTunnelDashState();publicstaticpartialboolHasDreamTunnelDash();publicstaticpartialintGetDreamTunnelDashCount();publicstaticpartialComponentDreamTunnelInteraction(Action<Player>onPlayerEnter,Action<Player>onPlayerExit);publicstaticpartialboolHasSeekerDash();publicstaticpartialboolIsSeekerDashAttacking();}Finally, call the Load() method on the import class. This method is automatically generated by the source generator.
// YourModModule.cspublicoverridevoidLoad(){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 IsImportedbool 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.csusingModInteropImportGenerator;[GenerateImports("CommunalHelper.DashStates",RequiredDependency=true)]publicstaticpartialclassDashStates{// ...}You can see the state of the import in the ImportState property of the import class.
Clone the project and build the ModInteropImportGenerator project. Prefer Release mode as it's
more optimized.