Skip to content

Latest commit

 

History

History
133 lines (110 loc) · 3.74 KB

default-func-with-readonlyspan.md

File metadata and controls

133 lines (110 loc) · 3.74 KB

Default Func with ReadOnlySpan

Pure.DI can generate the standard Func<ReadOnlySpan<char>, T> factory automatically. The runtime span argument is kept as a local value inside the generated delegate invocation, so no manual ctx.Override(...) call and no lock (ctx.Lock) block are required.

using Shouldly;
using Pure.DI;
using System;

DI.Setup(nameof(Composition))

    // Composition root
    .Root<Func<ReadOnlySpan<char>, Parser>>("ParserFactory");

var composition = new Composition();
var parser = composition.ParserFactory("Hello".AsSpan());

parser.Value.ShouldBe("Hello");

class Parser
{
    private string _value = "";

    [Ordinal]
    public void Initialize(ReadOnlySpan<char> text)
    {
        _value = text.ToString();
    }

    public string Value => _value;
}
Running this code sample locally
dotnet --list-sdk
  • Create a net10.0 (or later) console application
dotnet new console -n Sample
dotnet add package Pure.DI
dotnet add package Shouldly
  • Copy the example code into the Program.cs file

You are ready to run the example 🚀

dotnet run

Use this default Func binding when the standard delegate shape is enough. Use a custom delegate factory with explicit ctx.Override<T>(...) only when you need a custom delegate type or additional factory logic. This is the form to reach for when a hot path receives text as a span and must build an object from it without allocating an intermediate string: the span lives only inside the delegate call, and Parser.Initialize copies it once into a field. Because the span never escapes the invocation, the generated code needs no shared override state and therefore no lock. That is what makes the default binding cheaper and safer than a hand-written factory.

The following partial class will be generated
partial class Composition
{
  public Func<ReadOnlySpan<char>, Parser> ParserFactory
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      Func<ReadOnlySpan<char>, Parser> perBlockFuncReadOnlySpanCharParser;
      // Creates a factory with runtime arguments
      Func<ReadOnlySpan<char>, Parser> localFactory = new Func<ReadOnlySpan<char>, Parser>((ReadOnlySpan<char> localArg1) =>
      {
        // Creates the result
        ReadOnlySpan<char> overriddenReadOnlySpanChar = localArg1;
        var transientParser = new Parser();
        transientParser.Initialize(overriddenReadOnlySpanChar);
        return transientParser;
      });
      perBlockFuncReadOnlySpanCharParser = localFactory;
      return perBlockFuncReadOnlySpanCharParser;
    }
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Composition ..> FuncᐸReadOnlySpanᐸCharᐳˏParserᐳ : FuncᐸReadOnlySpanᐸCharᐳˏParserᐳ ParserFactory
	FuncᐸReadOnlySpanᐸCharᐳˏParserᐳ *-- Parser : Parser
	Parser *-- ReadOnlySpanᐸCharᐳ : ReadOnlySpanᐸCharᐳ
	namespace Pure.DI.UsageTests.BCL.DefaultFuncWithReadOnlySpanScenario {
		class Composition {
		<<partial>>
		+FuncᐸReadOnlySpanᐸCharᐳˏParserᐳ ParserFactory
		}
		class Parser {
				<<class>>
			+Parser()
			+Initialize(ReadOnlySpanᐸCharᐳ text) : Void
		}
	}
	namespace System {
		class FuncᐸReadOnlySpanᐸCharᐳˏParserᐳ {
			<<delegate>>
		}
		class ReadOnlySpanᐸCharᐳ {
			<<struct>>
		}
	}
Loading

See also: