Skip to content

IOL0ol1/LazyImport

Repository files navigation

LazyImport.Fody

NuGet Version NuGet Downloads

Convert DllImport methods to runtime loading.

This is an add-in for Fody

Usage

NuGet installation

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

PM> Install-Package Fody
PM> Install-Package LazyImport.Fody

Add to FodyWeavers.xml

Add <LazyImport/> to FodyWeavers.xml.

Example configuration:

<Weavers>
  <LazyImport>
    <Library Name="mylib" InitMethod="Initialize" />
  </LazyImport>
</Weavers>

How it Works

Here’s a typical P/Invoke class:

using System;
using System.Runtime.InteropServices;
public struct MyPoint
{
    public int X;
    public int Y;
    public MyPoint(int x, int y)
    {
        X = x;
        Y = y;
    }
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LogCallback([MarshalAs(UnmanagedType.LPStr)] string message);

public partial class NaticveMethods
{
    [DllImport("mylib",
        EntryPoint = "complex_function",
        CallingConvention = CallingConvention.Cdecl,
        SetLastError = true,
        ExactSpelling = false,
        PreserveSig = true,
        BestFitMapping = false,
        ThrowOnUnmappableChar = true)]
    public static extern void text_complex_all_attributes(
        [MarshalAs(UnmanagedType.LPWStr)] string input,
        [In, Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] int[] array,
        int arraySize,
        ref MyPoint point,
        out int status);

    [DllImport("mylib")]
    public static extern void test_callback_set_logger(LogCallback callback);
}

After installing LazyImport.Fody and setting up FodyWeavers.xml,
just build your project — the library will automatically rewrite P/Invoke methods to load at runtime.

(Optional) Manual Initialize Method

You can add InitMethod method stub to your P/Invoke class.
The actual implementation is automatically generated by Fody at compile time.

/// Other code...
public partial class NativeMethods
{
   public static void Initialize(IntPtr handle) 
     => throw new NotImplementedException("This method is implemented by Fody at compile time.");
   public static void Initialize(string handle) 
     => throw new NotImplementedException("This method is implemented by Fody at compile time.");

   /// Other code...
}

Dynamic Loading Example

static void Main(string[] args)
{
    // Load your native DLL
    NativeMethods.Initialize("path/to/mylib.dll"); 
    
    // Use P/Invoke methods normally
    var p = new MyPoint();
    NativeMethods.test_complex_all_attributes("111", new int[] { 1, 2, 3 }, 3, ref p, out int status);
}

Configuration

LazyImport supports two modes.

  • Dynamic mode (default): Rewrites P/Invoke methods to use runtime library loading and function pointer lookup.
  • Static mode: Only replaces the DLL name in DllImport — keeps normal P/Invoke behavior.

Basic dynamic configuration

<Weavers>
  <LazyImport>
    <Library Name="mylib" />
  </LazyImport>
</Weavers>

Equivalent explicit dynamic configuration:

<Weavers>
  <LazyImport>
    <Library Name="mylib" InitMethod="Initialize" />
  </LazyImport>
</Weavers>

Dynamic mode with Include/Exclude filters

<Weavers>
  <LazyImport>
    <Library
      Name="mylib"
      InitMethod="Initialize"
      Include="test_basic_*;test_string_*"
      Exclude="test_basic_legacy_*" />
  </LazyImport>
</Weavers>

Static mode (library name replacement)

<Weavers>
  <LazyImport>
    <Library Name="mylib" ReplaceName="__Internal" />
  </LazyImport>
</Weavers>

Mixed mode (multiple libraries)

<Weavers>
  <LazyImport>
    <Library Name="mylib" InitMethod="InitializeMyLib" Include="api_*" />
    <Library Name="mylib2" ReplaceName="__Internal" />
  </LazyImport>
</Weavers>

What is Generated Automatically?

In Dynamic Mode, LazyImport adds these to your class:

  • A library handle field
  • A function pointer field for each converted method
  • Two Initialize methods:
    Initialize(string dllPath)
    Initialize(IntPtr libraryHandle)

If you define the stub method, Fody will replace its body during build.

Important Notes

  • Name is required for every <Library>.
  • InitMethod and ReplaceName cannot be used together.
  • If neither is set, mode defaults to Dynamic.
  • InitMethod names must be unique across all libraries.
  • Include/Exclude support wildcards: * and ?.
  • If no libraries are configured, LazyImport will auto-detect DLLs from P/Invoke methods.
  • Auto-detect only works if exactly one native library is used.

(Optional) Custom Native Library Loader

You can implement your own loader by adding this class:

static class NativeLibraryLoader
{
    public static IntPtr Load(string path)
    {
        // Your custom logic to load the DLL
    }

    public static IntPtr GetExport(IntPtr handle, string symbolName)
    {
        // Your custom logic to get function pointer
    }
}

About

Fody add-in for rename DllImport or convert DllImport methods to runtime loading.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages