Hints are used to fine-tune code generation. The OnCannotResolve hint determines whether to generate a partial OnCannotResolve<T>(...) method to handle a scenario where an instance which cannot be resolved.
In addition, setup hints can be comments before the Setup method in the form hint = value, for example: // OnCannotResolveContractTypeNameRegularExpression = string.
using Shouldly;
using Pure.DI;
using static Pure.DI.Hint;
// The "OnCannotResolveContractTypeNameRegularExpression" hint defines a regular expression
// to filter the full type name of unresolved dependencies.
// In this case, we want to manually handle only "string" types.
// OnCannotResolveContractTypeNameRegularExpression = string
DI.Setup(nameof(Composition))
.Hint(OnCannotResolve, "On")
.Bind().To<DatabaseAccess>()
.Bind().To<BusinessService>()
.Root<IBusinessService>("BusinessService");
var composition = new Composition();
var businessService = composition.BusinessService;
// Check that the connection string was successfully injected via OnCannotResolve
businessService.DatabaseAccess.ConnectionString.ShouldBe("Server=localhost;Database=MyDb;");
interface IDatabaseAccess
{
string ConnectionString { get; }
}
// A service requiring a connection string.
// The connection string is a primitive type 'string' that is not bound in the DI setup.
// It will be resolved via the 'OnCannotResolve' fallback method.
class DatabaseAccess(string connectionString) : IDatabaseAccess
{
public string ConnectionString { get; } = connectionString;
}
interface IBusinessService
{
IDatabaseAccess DatabaseAccess { get; }
}
class BusinessService(IDatabaseAccess databaseAccess) : IBusinessService
{
public IDatabaseAccess DatabaseAccess { get; } = databaseAccess;
}
partial class Composition
{
// This method is called when a dependency cannot be resolved by the standard DI.
// It serves as a fallback mechanism.
private partial T OnCannotResolve<T>(
object? tag,
Lifetime lifetime)
{
// Check if the requested type is a string (according to the hint filter)
if (typeof(T) == typeof(string))
{
// Provide the configuration value (e.g., loaded from a file)
return (T)(object)"Server=localhost;Database=MyDb;";
}
throw new InvalidOperationException("Cannot resolve " + typeof(T));
}
}Running this code sample locally
- Make sure you have the .NET SDK 10.0 or later installed
dotnet --list-sdk- Create a net10.0 (or later) console application
dotnet new console -n Sampledotnet 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 runThe OnCannotResolveContractTypeNameRegularExpression hint helps define the set of types that require manual dependency resolution. You can use it to specify a regular expression to filter the full type name.
For more hints, see this page.
The following partial class will be generated:
partial class Composition
{
public IBusinessService BusinessService
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return new BusinessService(new DatabaseAccess(OnCannotResolve<string>(null, Lifetime.Transient)));
}
}
private partial T OnCannotResolve<T>(object? tag, Lifetime lifetime);
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
DatabaseAccess --|> IDatabaseAccess
BusinessService --|> IBusinessService
Composition ..> BusinessService : IBusinessService BusinessService
DatabaseAccess *-- String : String
BusinessService *-- DatabaseAccess : IDatabaseAccess
namespace Pure.DI.UsageTests.Hints.OnCannotResolveRegularExpressionHintScenario {
class BusinessService {
<<class>>
+BusinessService(IDatabaseAccess databaseAccess)
}
class Composition {
<<partial>>
+IBusinessService BusinessService
}
class DatabaseAccess {
<<class>>
+DatabaseAccess(String connectionString)
}
class IBusinessService {
<<interface>>
}
class IDatabaseAccess {
<<interface>>
}
}
namespace System {
class String {
<<class>>
}
}