DynaBee 1.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package DynaBee --version 1.2.1
                    
NuGet\Install-Package DynaBee -Version 1.2.1
                    
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="DynaBee" Version="1.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DynaBee" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="DynaBee" />
                    
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 DynaBee --version 1.2.1
                    
#r "nuget: DynaBee, 1.2.1"
                    
#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 DynaBee@1.2.1
                    
#: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=DynaBee&version=1.2.1
                    
Install as a Cake Addin
#tool nuget:?package=DynaBee&version=1.2.1
                    
Install as a Cake Tool

DynaBee

DynaBee is a lightweight .NET library that uses Reflection.Emit to generate dynamic types at runtime.

It is designed for scenarios where you need to build classes, methods, properties, and contracts programmatically, with a fluent API that is simple to use and easy to extend.

The recommended application model is DI-first: define DynaBeeProfile classes, let DynaBee discover them, and resolve generated assembly contexts through IDynaBeeAssemblyCatalog.

What It Solves

  • Runtime type generation without producing intermediate source code.
  • Fluent creation of classes, interfaces, structs, enums, and records.
  • Method implementation through IL, lambdas, or expression trees.
  • Dependency injection integration.
  • Typed metadata for external extensions (for example EF or other frameworks).
  • Assembly cache/versioning to reduce type build overhead.

Requirements

  • .NET SDK 10.0+ recommended for development.
  • The library multi-targets: net8.0, net9.0, and net10.0.

Installation

dotnet add package DynaBee

Getting Started

1) Define a profile

using DynaBee.FluentApi;
using DynaBee.FluentApi.DependencyInjection;
using System.Linq.Expressions;

public sealed class SalesProfile : DynaBeeProfile
{
    public SalesProfile() : base("Demo.Sales")
    {
    }

    public override void Configure(IBeeAssemblyBuilder builder)
    {
        builder
            .AddClass("Calculator", c => c
                .Implements<ICalculator>(registerInDi: true)
                .RegisterAsConcrete(false)
                .AddMethod(nameof(ICalculator.Sum), typeof(int), m => m
                    .WithParameter<int>("x")
                    .WithParameter<int>("y")
                    .EmitsExpression((Expression<Func<int, int, int>>)((x, y) => x + y))))
            .AddClass("InvoiceService", c => c
                .Implements<IInvoiceService>(registerInDi: true)
                .Implements<IInternalContract>(registerInDi: false)
                .RegisterAsConcrete(false)
                .Inject<IUnitOfWork>("UnitOfWork")
                .AddMethod(nameof(IInvoiceService.Commit), typeof(int), m => m
                    .EmitsInjectedLambda<IUnitOfWork, int>("UnitOfWork", uow => uow.SaveChanges())));
    }
}

public interface ICalculator
{
    int Sum(int x, int y);
}

public interface IInvoiceService
{
    int Commit();
}

public interface IInternalContract
{
    string Hidden();
}

public interface IUnitOfWork
{
    int SaveChanges();
}

2) Register DynaBee through DI

Profiles are the recommended way to organize dynamic types in larger applications. Each profile belongs to exactly one logical dynamic assembly. DynaBee discovers profiles, groups them by assembly name, builds each assembly context, and registers generated types in DI.

using DynaBee.FluentApi.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

services.AddSingleton<IUnitOfWork>(new UnitOfWork());

services.AddDynaBeeProfiles(
    ServiceLifetime.Transient,
    typeof(SalesProfile).Assembly);

var provider = services.BuildServiceProvider();
var catalog = provider.GetRequiredService<IDynaBeeAssemblyCatalog>();

var salesContext = catalog.GetContext("Demo.Sales");
var calculator = provider.GetRequiredService<ICalculator>();
var invoiceService = provider.GetRequiredService<IInvoiceService>();

var total = calculator.Sum(5, 3);        // 8
var rows = invoiceService.Commit();      // Calls IUnitOfWork.SaveChanges()

public sealed class UnitOfWork : IUnitOfWork
{
    public int SaveChanges() => 42;
}

3) Explicit registry setup

If you prefer explicit setup, AddDynaBeeRegistry(...) creates a single mutable registry/provider pair for one logical dynamic assembly and registers the initial generated types automatically.

using DynaBee.FluentApi.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System.Linq.Expressions;

var services = new ServiceCollection();

services.AddDynaBeeRegistry("Demo.Runtime", registry =>
{
    registry.Configure(builder => builder
        .AddClass("Greeter", c => c
            .AddMethod("SayHello", typeof(string), m => m
                .WithParameter<string>("name")
                .EmitsExpression((Expression<Func<string, string>>)(name => "Hello " + name)))));
});

var provider = services.BuildServiceProvider();
var context = provider.GetRequiredService<IAssemblyContext>();

4) Method body builder for mapper generation

EmitsBody(...) lets integrations build complete method bodies without using IL opcodes. It supports parameters, locals, object construction, instance/static property and field access, constants, default values, nullable checks, enum and numeric conversions, assignments, conditionals, and returns.

using DynaBee.FluentApi;
using DynaBee.FluentApi.DependencyInjection;
using System.Linq.Expressions;

public sealed class MappingProfile : DynaBeeProfile
{
    public MappingProfile() : base("Demo.Mapping")
    {
    }

    public override void Configure(IBeeAssemblyBuilder builder)
    {
        builder.AddClass("UserMapper", c => c
            .AddMethod("Map", typeof(UserDto), m => m
                .WithParameter<User>("source")
                .EmitsBody(body =>
                {
                    var source = body.Parameter<User>("source");
                    var destination = body.DeclareLocal<UserDto>("destination");

                    body.Assign(destination, body.New<UserDto>());
                    body.Assign(
                        body.Property(destination, nameof(UserDto.DisplayName)),
                        body.Concat(
                            body.Property(source, nameof(User.FirstName)),
                            body.Constant(" "),
                            body.Property(source, nameof(User.LastName))));
                    body.Assign(
                        body.Property(destination, nameof(UserDto.Total)),
                        body.Convert<decimal>(body.Property(source, nameof(User.Total))));
                    body.Assign(
                        body.Property(destination, nameof(UserDto.Name)),
                        body.If(
                            body.IsNull(body.Property(source, nameof(User.Name))),
                            body.Constant("Unknown"),
                            body.Property(source, nameof(User.Name))));
                    body.Return(destination);
                }));
    }
}

5) Cached method invokers

DynaBee can create cached invokers for generated methods. The invoker resolves reflection metadata once, compiles a dispatch bridge, and avoids MethodInfo.Invoke(...) during repeated calls.

using DynaBee.FluentApi.Invocation;

var mapper = context.CreateInstance("UserToUserDtoMapper");

var invoker = context.CreateBoundMethodInvoker(
    "UserToUserDtoMapper",
    mapper,
    "Map",
    new[] { typeof(User), typeof(IMapContext) });

var result = invoker.Invoke(new object[] { user, mapContext });

Multi-source methods use the same API:

var invoker = context.CreateBoundMethodInvoker(
    "OrderCustomerToOrderDtoMapper",
    mapper,
    "Map",
    new[] { typeof(Order), typeof(Customer), typeof(IMapContext) });

var result = invoker.Invoke(new object[] { order, customer, mapContext });

Real-World Use Cases

1) Plugin systems

Generate adapter types at runtime for plugin contracts discovered dynamically.

2) Multi-tenant applications

Create tenant-specific behavior types (validation rules, policy handlers, mapping profiles) without shipping many static assemblies.

3) Runtime API clients / SDK wrappers

Build strongly-typed runtime clients from metadata or schemas loaded from external systems.

4) Dynamic domain models

Generate entities or value objects from configuration (for example low-code platforms or metadata-driven apps).

5) Test doubles and runtime stubs

Create dynamic implementations for integration testing, custom mocks, or simulation environments.

6) High-performance dispatch layers

Emit optimized execution paths for expression-based pipelines where reflection-only invocation is too expensive.

7) Framework integrations via metadata

Attach typed metadata in Fluent API, then consume it in external packages (for example EF mapping hints like table/column/type, custom serialization hints, validation hints).

8) Metadata-driven EF or API model bootstrapping

Use profiles to group dynamic entity definitions by logical assembly, then resolve the generated IAssemblyContext through IDynaBeeAssemblyCatalog while bootstrapping framework integrations.

Benchmarks

Command:

dotnet run -c Release -f net8.0 --project benchmarks/DynaBee.Benchmarks/DynaBee.Benchmarks.csproj -- --filter *

Measured results:

Benchmark Mean Allocated
CreateInstance 90.70 ns 200 B
CallViaInterface 1.52 ns 0 B
CallViaReflection 25.17 ns 24 B
BuildClass_NoCache 276.40 us 10,569 B
BuildClass_FromCache 43.16 ns 144 B

Notes:

  • BuildClass_NoCache and BuildClass_FromCache were executed with ShortRun.
  • Cache dramatically reduces repeated build cost.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on DynaBee:

Package Downloads
TurtlePath.Automations

Declarative automation profiles and generated handler registration for TurtlePath application flows.

Crabalidator

Crabalidator is a high-performance .NET validation library powered by DynaBee-generated runtime validators.

OctoMap

OctoMap is a lightweight .NET object mapping library powered by DynaBee-generated runtime mappers.

DynaBee.Testing

Testing helpers for DynaBee generated assemblies, generated types, diagnostics, dependency injection registration, and generated source snapshots.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.4.0 397 8/7/2026
1.3.0 1,033 7/31/2026
1.2.6 1,069 7/20/2026
1.2.5 109 7/19/2026
1.2.4 113 7/18/2026
1.2.3 107 7/17/2026
1.2.2 107 7/17/2026
1.2.1 106 7/16/2026
1.2.0 110 7/16/2026
1.1.0 115 7/14/2026
1.0.1 138 4/6/2026
1.0.0 106 4/6/2026