LazyImport.Fody
1.0.4
dotnet add package LazyImport.Fody --version 1.0.4
NuGet\Install-Package LazyImport.Fody -Version 1.0.4
<PackageReference Include="LazyImport.Fody" Version="1.0.4" />
<PackageVersion Include="LazyImport.Fody" Version="1.0.4" />
<PackageReference Include="LazyImport.Fody" />
paket add LazyImport.Fody --version 1.0.4
#r "nuget: LazyImport.Fody, 1.0.4"
#:package LazyImport.Fody@1.0.4
#addin nuget:?package=LazyImport.Fody&version=1.0.4
#tool nuget:?package=LazyImport.Fody&version=1.0.4
LazyImport.Fody
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
Initializemethods:
Initialize(string dllPath)
Initialize(IntPtr libraryHandle)
If you define the stub method, Fody will replace its body during build.
Important Notes
Nameis required for every<Library>.InitMethodandReplaceNamecannot be used together.- If neither is set, mode defaults to Dynamic.
InitMethodnames must be unique across all libraries.Include/Excludesupport 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
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net452 is compatible. net46 was computed. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.