Skip to content

Commit

Permalink
RX State improve Observable and simplify service states
Browse files Browse the repository at this point in the history
Simplify observable states and remove dedicated service state providers
  • Loading branch information
Bernhard Straub committed Feb 25, 2024
1 parent 30d445e commit 4da6261
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 167 deletions.
22 changes: 12 additions & 10 deletions RxBlazorLightCore/Core/Interfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public interface IState<TInterface, TType> : IStateTransformer<TType> where TTyp

public interface IState<TType> : IState<TType, TType>;

public interface IState : IState<object?, object?>
public interface IState : IState<Unit, Unit>
{
public static object? Default { get; } = default;
public static Unit Default { get; } = Unit.Default;
}

public interface IStateGroup<TType> : IState<TType>
Expand All @@ -64,6 +64,7 @@ public enum StateChangePhase
NONE,
CHANGING,
CHANGED,
COMPLETED,
CANCELED,
EXCEPTION
}
Expand All @@ -84,23 +85,24 @@ public interface IStateTransformer<T> : IStateProvideTransformBase
public bool CanTransform(T? value);
}

public interface IStateProvider<T> : IStateProvideTransformBase
public interface IObservableStateProvider<T> : IStateProvideTransformBase, IObserver<T>
{
public void Provide();

public bool CanProvide(T? value);
void Provide(T value);
}

public interface IServiceStateTransformer<T> : IStateTransformer<T>
public interface IObservableStateProvider : IObservableStateProvider<Unit>
{
void Provide();
}

public interface IServiceStateProvider : IStateProvider<object?>
public interface IStateProvider<T> : IStateProvideTransformBase
{
public void Provide();

public bool CanProvide(T? value);
}

public interface IServiceStateObserver : IObserver<Unit>, IStateProvideTransformBase
public interface IStateProvider : IStateProvider<Unit>
{
public void Provide();
}
}
16 changes: 14 additions & 2 deletions RxBlazorLightCore/Core/RxExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using System.Reactive;

namespace RxBlazorLightCore
{
public static class RxExtensions
Expand All @@ -15,9 +17,14 @@ public static IState<TType> CreateState<S, TType>(this S service, TType? value,
return State<S, TType>.Create(service, value, valueProviderFactory);
}

public static IServiceStateObserver CreateStateObserver<S>(this S service) where S : RxBLService
public static IObservableStateProvider<Unit> CreateObservableStateProvider<S>(this S service) where S : RxBLService
{
return ObservableStateProvider<S, Unit>.Create(service);
}

public static IObservableStateProvider<T> CreateObservableStateProvider<S, T>(this S service, IState<T> state) where S : RxBLService
{
return new ServiceStateObserver<S>(service);
return ObservableStateProvider<S, T>.Create(service, state);
}

public static bool Changing(this IStateProvideTransformBase valueProvider)
Expand All @@ -30,6 +37,11 @@ public static bool Changed(this IStateProvideTransformBase valueProvider)
return valueProvider.Phase is StateChangePhase.CHANGED;
}

public static bool Completed(this IStateProvideTransformBase valueProvider)
{
return valueProvider.Phase is StateChangePhase.COMPLETED;
}

public static bool Canceled(this IStateProvideTransformBase valueProvider)
{
return valueProvider.Phase is StateChangePhase.CANCELED;
Expand Down
173 changes: 62 additions & 111 deletions RxBlazorLightCore/Core/State.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@

using System.Numerics;
using System.Reactive;
using System.Reactive.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace RxBlazorLightCore
{
Expand Down Expand Up @@ -79,7 +77,7 @@ public static IState<TType> Create(S service, TType? value, Func<IState<TType>,
}
}

public class State<S> : State<S, object?, object?>, IState
public class State<S> : State<S, Unit, Unit>, IState
where S : RxBLService
{
private State(S service) : base(service, IState.Default, null) { }
Expand Down Expand Up @@ -164,7 +162,7 @@ public class StateProvideTransformBase<S, T, TInterface, TType> : IStateProvideT
protected internal StateProvideTransformBase(S service, IState<TInterface, TType>? state, bool setState, bool runAsync)
{
Service = service;
State = state is null ? (State<S, TInterface, TType>)State<S, object?, object?>.Create(service, IState.Default) : (State<S, TInterface, TType>)state;
State = state is null ? (State<S, TInterface, TType>)State<S, Unit, Unit>.Create(service, IState.Default) : (State<S, TInterface, TType>)state;
_setState = setState;
_runAsync = runAsync;
_canceled = false;
Expand Down Expand Up @@ -326,6 +324,57 @@ public void Transform(T value)
protected abstract TType? TransformState(T value);
}

public class ObservableStateProvider<S, T>(S service, IState<T>? state) :
StateProvideTransformBase<S, T, T, T>(service, state, true, false), IObservableStateProvider<T>
where S : RxBLService
{
public void OnCompleted()
{
StateChanged(StateChangePhase.COMPLETED);
}

public void OnError(Exception error)
{
StateChanged(StateChangePhase.EXCEPTION, error);
}

public void OnNext(T value)
{
TransformBaseSync(value);
}

public void Provide(T value)
{
OnNext(value);
}

public static IObservableStateProvider<Unit> Create(S service)
{
var state = State<S, Unit>.Create(service, Unit.Default);
return new ObservableStateProvider<S, Unit>(service, state);
}

public static IObservableStateProvider<T> Create(S service, IState<T> state)
{
return new ObservableStateProvider<S, T>(service, state);
}
}

public class ObservableStateProvider<S>(S service) : ObservableStateProvider<S, Unit>(service, null),
IObservableStateProvider
where S : RxBLService
{
public void Provide()
{
Provide(Unit.Default);
}

public static new IObservableStateProvider Create(S service)
{
return new ObservableStateProvider<S>(service);
}
}

public abstract class StateProviderAsync<S, T>(S service, IState<T> state) :
StateProvideTransformBase<S, T, T, T>(service, state, true, true), IStateProvider<T>
where S : RxBLService
Expand Down Expand Up @@ -429,66 +478,11 @@ public void Transform(T value)
protected abstract void TransformState(T value, TType stateRef);
}

public abstract class ServiceStateTransformerAsync<S, T>(S service) :
StateProvideTransformBase<S, T?, object?, object?>(service, null, true, true), IServiceStateTransformer<T>
where T : notnull
where S : RxBLService
{
public virtual bool CanTransform(T? _)
{
return true;
}

public void Transform(T value)
{
TransformBaseAsync(value);
}

protected override IObservable<object?> ProvideObervableValueBase(T? value, object? state)
{
ArgumentNullException.ThrowIfNull(value);

return Observable.FromAsync(async cto =>
{
await TransformStateAsync(value, cto);
return IState.Default;
});
}

protected abstract Task TransformStateAsync(T value, CancellationToken cancellationToken);
}

public abstract class ServiceStateTransformer<S, T>(S service) :
StateProvideTransformBase<S, T?, object?, object?>(service, null, true, false), IServiceStateTransformer<T>
where T : notnull
where S : RxBLService
{
public virtual bool CanTransform(T? _)
{
return true;
}

public void Transform(T value)
{
try
{
TransformState(value);
TransformBaseSync(IState.Default);
}
catch (Exception ex)
{
StateChanged(StateChangePhase.EXCEPTION, ex);
}
}

protected abstract void TransformState(T value);
}

public abstract class ServiceStateProviderAsync<S>(S service) :
StateProvideTransformBase<S, object?, object?, object?>(service, null, true, true), IServiceStateProvider
public abstract class StateProviderAsync<S>(S service) :
StateProvideTransformBase<S, Unit, Unit, Unit>(service, null, true, true), IStateProvider
where S : RxBLService
{
public bool CanProvide(object? _)
public bool CanProvide(Unit _)
{
return CanProvide();
}
Expand All @@ -503,7 +497,7 @@ public void Provide()
TransformBaseAsync(IState.Default);
}

protected override IObservable<object?> ProvideObervableValueBase(object? value, object? state)
protected override IObservable<Unit> ProvideObervableValueBase(Unit value, Unit state)
{
return Observable.FromAsync(async cto =>
{
Expand All @@ -515,11 +509,11 @@ public void Provide()
protected abstract Task ProvideStateAsync(CancellationToken cancellationToken);
}

public abstract class ServiceStateProvider<S>(S service) :
StateProvideTransformBase<S, object?, object?, object?>(service, null, false, false), IServiceStateProvider
public abstract class StateProvider<S>(S service) :
StateProvideTransformBase<S, Unit, Unit, Unit>(service, null, false, false), IStateProvider
where S : RxBLService
{
public bool CanProvide(object? _)
public bool CanProvide(Unit _)
{
return CanProvide();
}
Expand All @@ -542,54 +536,11 @@ public void Provide()
}
}

protected override IObservable<object?> ProvideObervableValueBase(object? value, object? state)
protected override IObservable<Unit> ProvideObervableValueBase(Unit value, Unit state)
{
return Observable.Return(Unit.Default).Select(_ =>
{
ProvideState();
return IState.Default;
});
return Observable.Return(Unit.Default);
}

protected abstract void ProvideState();
}

public class ServiceStateObserver<S>(S service) : IServiceStateObserver where S : RxBLService
{
public Guid ID { get; } = Guid.NewGuid();

public StateChangePhase Phase { get; private set; } = StateChangePhase.NONE;

public bool LongRunning => false;

public bool CanCancel => false;

public void Cancel()
{
throw new NotImplementedException();
}

public void Provide()
{
OnNext(Unit.Default);
}

public void OnCompleted()
{
Phase = StateChangePhase.CANCELED;
service.StateHasChanged(ID, ChangeReason.STATE);
}

public void OnError(Exception error)
{
Phase = StateChangePhase.EXCEPTION;
service.StateHasChanged(ID, ChangeReason.EXCEPTION, error);
}

public void OnNext(Unit value)
{
Phase = StateChangePhase.CHANGED;
service.StateHasChanged(ID, ChangeReason.STATE);
}
}
}
9 changes: 4 additions & 5 deletions RxBlazorLightCoreTestBase/ServiceFixture.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,18 @@ protected override async Task<int> TransformStateAsync(int value, CancellationTo
}
}

public class ChangeTestSP(ServiceFixture service) : ServiceStateTransformerAsync<ServiceFixture, string>(service)
public class ChangeTestSP(ServiceFixture service) : StateProviderAsync<ServiceFixture>(service)
{
public override bool CanCancel => true;

protected override async Task TransformStateAsync(string? valueIn, CancellationToken cancellationToken)
protected override async Task ProvideStateAsync(CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(valueIn);
await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
Service.Test = valueIn;
Service.Test = "Async";
}
}

public class ChangeTestSyncSP(ServiceFixture service) : ServiceStateProvider<ServiceFixture>(service)
public class ChangeTestSyncSP(ServiceFixture service) : StateProvider<ServiceFixture>(service)
{
protected override void ProvideState()
{
Expand Down
Loading

0 comments on commit 4da6261

Please sign in to comment.