feat: new ValueProvider improvements and source generator.
This commit is contained in:
@@ -5,18 +5,25 @@ namespace GodotHostTest.AetherBind;
|
||||
public static class BuilderExtensions
|
||||
{
|
||||
public static Builder AddValueProvider<TValueType, TSourceScope, TDestinationScope>(this Builder builder)
|
||||
where TValueType : class
|
||||
where TSourceScope : RootScope
|
||||
where TDestinationScope : TSourceScope
|
||||
{
|
||||
var valueProvider = new ValueProvider<TValueType>();
|
||||
return builder
|
||||
// add the setter to the source scope
|
||||
.AddScoped<IValueSetter<TValueType>, IValueSetter<TValueType>, TSourceScope>(Builder.NoDependencies,
|
||||
_ => valueProvider.Setter)
|
||||
// add the getter to the destination scope
|
||||
.AddScoped<IValueGetter<TValueType>, IValueGetter<TValueType>, TDestinationScope>(Builder.NoDependencies,
|
||||
_ => valueProvider.Getter);
|
||||
_ => valueProvider.Getter)
|
||||
// add a factory to automatically extract TValueType from the IValueGetter<TValueType>
|
||||
.AddScoped<TValueType, TValueType, TDestinationScope>(_ => [typeof(IValueGetter<TValueType>)],
|
||||
provider => provider.Get<IValueGetter<TValueType>>().Value);
|
||||
}
|
||||
|
||||
public static Builder AddValueProvider<TValueType, TScope>(this Builder builder)
|
||||
where TValueType : class
|
||||
where TScope : RootScope
|
||||
{
|
||||
return builder.AddValueProvider<TValueType, TScope, TScope>();
|
||||
|
||||
@@ -15,4 +15,31 @@ TOC:
|
||||
- deep dive into why it's all done at composition root
|
||||
- using extension methods to split the code as necessary
|
||||
- sending data into a scope
|
||||
- initializing data in the scope
|
||||
- initializing data in the scope
|
||||
|
||||
NOTES
|
||||
|
||||
field with \[Inject\] or method with \[Inject\] automatically receive injection IF they are between the injected objects
|
||||
of a ServiceSource
|
||||
|
||||
a method with \[WithProvider\] generates a companion method for unwrapping provider. E.g.:
|
||||
|
||||
```csharp
|
||||
[WithProvider]
|
||||
private void OnReady(IService1 service1, IService2 service2)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
will generate a companion method similar to:
|
||||
|
||||
```csharp
|
||||
private void OnReadyWithProvider(IProvider provider)
|
||||
{
|
||||
OnReady(
|
||||
provider.Get<IService1>(),
|
||||
provider.Get<IService2>()
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -3,13 +3,14 @@ using System;
|
||||
namespace GodotHostTest.AetherBind;
|
||||
|
||||
/// <summary>
|
||||
/// An object that allows communication through scopes, by providing a couple getter/setter that can be injected in
|
||||
/// different scopes.
|
||||
/// An object that allows communication through scopes (or inside the scope itself) by providing a couple getter/setter that can be injected in different scopes (or the same scope).
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type that's been passed through scopes.</typeparam>
|
||||
/// <seealso cref="BuilderExtensions.AddValueProvider" />
|
||||
/// <seealso cref="BuilderExtensions.AddValueProvider{TValueType,TScope}" />
|
||||
/// <seealso cref="BuilderExtensions.AddValueProvider{TValueType,TSourceScope,TDestinationScope}" />
|
||||
public class ValueProvider<T>
|
||||
{
|
||||
private IValueGetter<T>? _getter;
|
||||
private bool _isSet;
|
||||
private T? _value;
|
||||
|
||||
@@ -20,9 +21,16 @@ public class ValueProvider<T>
|
||||
|
||||
public IValueSetter<T> Setter { get; }
|
||||
|
||||
public IValueGetter<T> Getter => !_isSet
|
||||
? throw new InvalidOperationException($"Value of type {typeof(T)} has not been set yet.")
|
||||
: new GetterImplementation(_value!);
|
||||
public IValueGetter<T> Getter
|
||||
{
|
||||
get
|
||||
{
|
||||
_getter ??= !_isSet
|
||||
? throw new InvalidOperationException($"Value of type {typeof(T)} has not been set yet.")
|
||||
: new GetterImplementation(_value!);
|
||||
return _getter;
|
||||
}
|
||||
}
|
||||
|
||||
private class SetterImplementation(ValueProvider<T> valueProvider) : IValueSetter<T>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user