DynaBee.Testing 1.4.0

dotnet add package DynaBee.Testing --version 1.4.0
                    
NuGet\Install-Package DynaBee.Testing -Version 1.4.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="DynaBee.Testing" Version="1.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DynaBee.Testing" Version="1.4.0" />
                    
Directory.Packages.props
<PackageReference Include="DynaBee.Testing" />
                    
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.Testing --version 1.4.0
                    
#r "nuget: DynaBee.Testing, 1.4.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 DynaBee.Testing@1.4.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=DynaBee.Testing&version=1.4.0
                    
Install as a Cake Addin
#tool nuget:?package=DynaBee.Testing&version=1.4.0
                    
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, expression trees, or high-level method body builders.
  • Dependency injection integration.
  • DI-first generation plans that consumer libraries can inspect before emission.
  • Base constructor forwarding and virtual/abstract method or property overrides without consumer-side emit plumbing.
  • Selective DI registration as concrete types, interfaces, or arbitrary assignable service/base types.
  • 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

For test projects that validate generated assemblies:

dotnet add package DynaBee.Testing

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) Descriptor-driven generation plans

Consumer libraries can normalize their own descriptors into a DynaBee generation plan, inspect that plan before emission, and then apply it to any IBeeAssemblyBuilder supplied by the DI-first registry/factory pipeline.

Plans are generic: they describe runtime types, inheritance, implemented interfaces, constructors, members, DI registration metadata, and descriptor correlation metadata. They do not impose application-level semantics.

using DynaBee.FluentApi;
using DynaBee.FluentApi.DependencyInjection;
using DynaBee.FluentApi.Generation;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

var executeMethod = typeof(RuntimeHandlerBase)
    .GetMethod(nameof(RuntimeHandlerBase.Execute))!;

var baseConstructor = typeof(RuntimeHandlerBase)
    .GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        binder: null,
        new[] { typeof(IServiceProvider) },
        modifiers: null)!;

var plan = new DynaBeeGenerationPlan("Demo.Handlers")
    .WithMetadata("descriptor.batch", "handlers-v1")
    .AddClass("GeneratedHandler", type => type
        .Inherits(typeof(RuntimeHandlerBase))
        .RegisterAs(typeof(RuntimeHandlerBase))
        .RegisterAsConcrete(false)
        .WithMetadata("descriptor.key", "handler:orders")
        .AddConstructor(ctor => ctor
            .WithParameter<IServiceProvider>("serviceProvider")
            .CallsBase(baseConstructor, args => args.Argument("serviceProvider")))
        .OverrideMethod(executeMethod, method => method
            .EmitsBody(body => body.Return(body.Constant("Handled")))));

// The plan can be inspected before any dynamic type is emitted.
var plannedClass = plan.Classes[0];
Console.WriteLine(plannedClass.BaseType);
Console.WriteLine(plannedClass.Metadata["descriptor.key"]);

var services = new ServiceCollection();
services.AddSingleton<NameFormatter>();
services.AddDynaBeeRegistry(plan.AssemblyName, registry =>
{
    registry.Configure(builder => plan.ApplyTo(builder));
});

var provider = services.BuildServiceProvider();
var handler = provider.GetRequiredService<RuntimeHandlerBase>();

var result = handler.Execute("orders"); // "Handled"

public abstract class RuntimeHandlerBase
{
    protected RuntimeHandlerBase(IServiceProvider serviceProvider)
    {
        Formatter = serviceProvider.GetRequiredService<NameFormatter>();
    }

    protected NameFormatter Formatter { get; }

    public abstract string Execute(string input);
}

public sealed class NameFormatter
{
    public string Format(string value) => $"Formatted: {value}";
}

Generated classes can also override virtual or abstract properties:

var nameProperty = typeof(RuntimeQueryBase)
    .GetProperty(nameof(RuntimeQueryBase.Name))!;

registry.Configure(builder => builder
    .AddClass("GeneratedQuery", type => type
        .Inherits(typeof(RuntimeQueryBase))
        .OverrideProperty(nameProperty, property => property
            .WithMetadata("descriptor.member", "query:name")
            .Getter(get => get.ReturnsConstant("Orders")))));

public abstract class RuntimeQueryBase
{
    public virtual string Name => "Base";
}

5) 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, method calls, access to the generated instance through Self(), side-effect evaluation, 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);
                }));
    }
}

6) DI-based resolver method bodies

DynaBee does not own service lifetimes. Instead, generated method bodies can call whatever service provider or resolver API your integration chooses. This keeps framework-specific concerns outside the core library while still avoiding direct IL in integrations.

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

public sealed class ResolverProfile : DynaBeeProfile
{
    public ResolverProfile() : base("Demo.Resolvers")
    {
    }

    public override void Configure(IBeeAssemblyBuilder builder)
    {
        var getRequiredService = typeof(ServiceProviderServiceExtensions)
            .GetMethods()
            .Single(x => x.Name == nameof(ServiceProviderServiceExtensions.GetRequiredService)
                && x.IsGenericMethodDefinition
                && x.GetParameters().Length == 1)
            .MakeGenericMethod(typeof(OrderTotalTextResolver));

        var resolveMethod = typeof(IValueResolver<Order, OrderDto, string>)
            .GetMethod(nameof(IValueResolver<Order, OrderDto, string>.Resolve))!;

        builder.AddClass("OrderMapper", c => c
            .AddMethod("Map", typeof(OrderDto), m => m
                .WithParameter<Order>("source")
                .WithParameter<IMapContext>("mapContext")
                .EmitsBody(body =>
                {
                    var source = body.Parameter<Order>("source");
                    var mapContext = body.Parameter<IMapContext>("mapContext");
                    var destination = body.DeclareLocal<OrderDto>("destination");
                    var resolver = body.DeclareLocal<OrderTotalTextResolver>("resolver");

                    body.Assign(destination, body.New<OrderDto>());
                    body.Assign(
                        resolver,
                        body.StaticCall(
                            getRequiredService,
                            body.Property(mapContext, nameof(IMapContext.Services))));
                    body.Assign(
                        body.Property(destination, nameof(OrderDto.TotalText)),
                        body.Call(resolver, resolveMethod, source, destination, mapContext));
                    body.Return(destination);
                })));
    }
}

public interface IMapContext
{
    IServiceProvider Services { get; }
}

public interface IValueResolver<in TSource, in TDestination, out TMember>
{
    TMember Resolve(TSource source, TDestination destination, IMapContext context);
}

public sealed class OrderTotalTextResolver
    : IValueResolver<Order, OrderDto, string>
{
    public string Resolve(Order source, OrderDto destination, IMapContext context)
        => source.Total.ToString("C");
}

Generated methods can also call collaborators stored on the generated instance:

builder.AddClass("OrderMapper", c => c
    .AddAutoProperty<IOrderFormatter>("Formatter")
    .AddMethod("Format", typeof(string), m => m
        .WithParameter<Order>("source")
        .EmitsBody(body =>
        {
            var formatter = body.Property(body.Self(), "Formatter");
            var source = body.Parameter<Order>("source");
            var format = typeof(IOrderFormatter).GetMethod(nameof(IOrderFormatter.Format))!;

            body.Return(body.Call(formatter, format, source));
        })));

7) Collection method bodies

Collection-oriented generated methods can use loops, ordered comparisons, indexed access, runtime-sized arrays, and constructor calls with arguments. This lets integrations generate array/list mapping logic without helper delegates, reflection invocation, expression compilation, or raw IL.

public sealed class CollectionProfile : DynaBeeProfile
{
    public CollectionProfile() : base("Demo.Collections")
    {
    }

    public override void Configure(IBeeAssemblyBuilder builder)
    {
        builder.AddClass("ArrayCopier", c => c
            .AddMethod("Copy", typeof(int[]), m => m
                .WithParameter<int[]>("source")
                .EmitsBody(body =>
                {
                    var source = body.Parameter<int[]>("source");
                    var destination = body.DeclareLocal<int[]>("destination");
                    var index = body.DeclareLocal<int>("i");

                    body.If(body.IsNull(source), whenTrue: branch =>
                    {
                        branch.Return(branch.Constant(null, typeof(int[])));
                    });

                    body.Assign(
                        destination,
                        body.NewArray<int>(body.Property(source, nameof(Array.Length))));

                    body.For(
                        initialize: loop => loop.Assign(index, loop.Constant(0)),
                        condition: loop => loop.LessThan(
                            index,
                            loop.Property(source, nameof(Array.Length))),
                        increment: loop => loop.Assign(
                            index,
                            loop.Add(index, loop.Constant(1))),
                        body: loop => loop.Assign(
                            loop.Index(destination, index),
                            loop.Index(source, index)));

                    body.Return(destination);
                })));
    }
}

The same primitives can generate list transformations with per-item method calls:

var addMethod = typeof(List<OrderItemDto>)
    .GetMethod(nameof(List<OrderItemDto>.Add))!;
var mapMethod = typeof(IItemMapper)
    .GetMethod(nameof(IItemMapper.Map))!;

builder.AddClass("ItemMapperAdapter", c => c
    .AddMethod("MapItems", typeof(List<OrderItemDto>), m => m
        .WithParameter<List<OrderItem>>("source")
        .WithParameter<IItemMapper>("mapper")
        .EmitsBody(body =>
        {
            var source = body.Parameter<List<OrderItem>>("source");
            var mapper = body.Parameter<IItemMapper>("mapper");
            var destination = body.DeclareLocal<List<OrderItemDto>>("destination");
            var index = body.DeclareLocal<int>("i");

            body.If(body.IsNull(source), whenTrue: branch =>
            {
                branch.Return(branch.Constant(null, typeof(List<OrderItemDto>)));
            });

            body.Assign(
                destination,
                body.New(
                    typeof(List<OrderItemDto>),
                    body.Property(source, nameof(List<OrderItem>.Count))));

            body.For(
                initialize: loop => loop.Assign(index, loop.Constant(0)),
                condition: loop => loop.LessThan(
                    index,
                    loop.Property(source, nameof(List<OrderItem>.Count))),
                increment: loop => loop.Assign(
                    index,
                    loop.Add(index, loop.Constant(1))),
                body: loop => loop.Evaluate(loop.Call(
                    destination,
                    addMethod,
                    loop.Call(mapper, mapMethod, loop.Index(source, index)))));

            body.Return(destination);
        })));

For non-indexed sources such as IEnumerable<T>, use ForEach(...). DynaBee emits the enumerator pattern and disposes the enumerator when enumeration ends.

var addMethod = typeof(List<string>)
    .GetMethod(nameof(List<string>.Add))!;

builder.AddClass("EnumerableCopier", c => c
    .AddMethod("Copy", typeof(List<string>), m => m
        .WithParameter<IEnumerable<string>>("source")
        .EmitsBody(body =>
        {
            var source = body.Parameter<IEnumerable<string>>("source");
            var destination = body.DeclareLocal<List<string>>("destination");

            body.Assign(destination, body.New<List<string>>());
            body.ForEach(source, "item", (item, loop) =>
            {
                loop.Evaluate(loop.Call(destination, addMethod, item));
            });
            body.Return(destination);
        })));

Method bodies can also express richer computed values without falling back to raw IL:

builder.AddClass("ExpressionMapper", c => c
    .AddMethod("Compute", typeof(int), m => m
        .WithParameter<int>("x")
        .WithParameter<int>("y")
        .EmitsBody(body =>
        {
            var x = body.Parameter<int>("x");
            var y = body.Parameter<int>("y");

            body.Return(body.Add(
                body.Multiply(body.Subtract(x, y), body.Constant(2)),
                body.Modulo(x, y)));
        }))
    .AddMethod("NameOrDefault", typeof(string), m => m
        .WithParameter<string>("name")
        .EmitsBody(body =>
        {
            body.Return(body.Coalesce(
                body.Parameter<string>("name"),
                body.Constant("Unknown")));
        })));

8) Generated dispatch delegates

When callers know the delegate shape they want, DynaBee can create typed delegates for generated methods and constructors. Method lookup happens once, then repeated calls use the compiled delegate path instead of reflection invocation.

using DynaBee.FluentApi.Invocation;

var context = catalog.GetContext("Demo.Runtime");
var adder = context.CreateInstance("GeneratedAdder");

var add = context.CreateBoundDelegate<Func<int, int, int>>(
    "GeneratedAdder",
    adder,
    "Add",
    new[] { typeof(int), typeof(int) });

var result = add(1, 2); // 3

Open delegates keep the generated instance as the first delegate parameter:

var openAdd = context.CreateOpenDelegate<Func<object, int, int, int>>(
    "GeneratedAdder",
    "Add",
    new[] { typeof(int), typeof(int) });

var result = openAdd(adder, 1, 2);

Constructor factories avoid consumer-side reflection when creating generated instances with constructor arguments:

var createGreeter = context.CreateFactoryDelegate<Func<string, object>>(
    "GeneratedGreeter",
    new[] { typeof(string) });

var greeter = createGreeter("Ada");

Consumers that discover delegate types at runtime can still let DynaBee own delegate creation:

var delegateType = typeof(Func<int, int, int>);

var add = (Func<int, int, int>)context.CreateBoundDelegate(
    delegateType,
    "GeneratedAdder",
    adder,
    "Add",
    new[] { typeof(int), typeof(int) });

For diagnostics, tracing, and cache keys, generated methods can be described with stable metadata:

var descriptor = context.GetGeneratedMethodDescriptor(
    "GeneratedAdder",
    "Add",
    new[] { typeof(int), typeof(int) });

Console.WriteLine($"{descriptor.DeclaringType.Name}.{descriptor.Name}");

Object adapters are available for dynamic fallback paths without consumer-side reflection invocation. Fixed-arity adapters avoid per-call object[] allocation for common hot paths:

var addAdapter = context.CreateObjectAdapter2(
    "GeneratedAdder",
    adder,
    "Add",
    new[] { typeof(int), typeof(int) });

var sum = addAdapter(1, 2); // boxed 3

For higher arity, use an argument-list adapter with stable method metadata:

var adapter = context.CreateArgumentListAdapter(
    "GeneratedAggregator",
    aggregator,
    "Sum",
    new[]
    {
        typeof(int), typeof(int), typeof(int), typeof(int), typeof(int),
        typeof(int), typeof(int), typeof(int), typeof(int), typeof(int)
    });

var total = adapter.Invoke(new object[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

9) 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 });

10) Testing generated assemblies

DynaBee.Testing provides a small testing layer for generated assemblies, generated types, diagnostics, dependency injection registration, and source snapshots. It does not depend on any application framework-specific package.

using DynaBee.Testing;
using DynaBee.Testing.Assertions;
using DynaBee.Testing.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System.Linq.Expressions;

var services = new ServiceCollection()
    .AddDynaBeeTesting();

var provider = services.BuildServiceProvider();
var dynabeeTest = provider.GetRequiredService<IDynaBeeTestGenerator>();

var specification = DynaBeeTestSpecification.Create("Demo.Tests", builder => builder
    .AddClass("CreateCustomerCommandHandler", type => type
        .Implements<IRequestHandler<CreateCustomerCommand, CustomerCreated>>()
        .AddMethod("Handle", typeof(CustomerCreated), method => method
            .WithParameter<CreateCustomerCommand>("request")
            .EmitsExpression(
                (Expression<Func<CreateCustomerCommand, CustomerCreated>>)
                (request => new CustomerCreated())))));

var result = await dynabeeTest.GenerateAssemblyAsync(specification);
var assembly = result.Assembly;

result.Diagnostics.ShouldBeEmpty();
var generatedType = assembly.ShouldContainType("CreateCustomerCommandHandler");
generatedType.ShouldImplement(typeof(IRequestHandler<,>));

services.AddGeneratedAssembly(assembly);

result.WriteGeneratedSourcesTo("./snapshots/generated");

Useful assertions include generated assembly existence, generated type existence, constructor shape, implemented interfaces, inherited base types, generic arguments, diagnostics, and source snapshot output.

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.

9) Descriptor-driven handler generation

Transform normalized descriptors into generated classes that inherit framework base types, forward constructor dependencies, override virtual behavior, and register as runtime handler services.

10) Replaceable generation backends

Keep consumer libraries open to alternate generation strategies by converting their descriptors into DynaBeeGenerationPlan instances and applying those plans through IBeeAssemblyBuilder.

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 (1)

Showing the top 1 NuGet packages that depend on DynaBee.Testing:

Package Downloads
TurtlePath.Testing.Integration

Integration testing wrappers that compose TurtlePath.Testing with Elysium testing adapters.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.4.0 389 8/7/2026