Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LifeCycle to FluxorOptions and use in registration #287

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Fluxor.Blazor.Web.ReduxDevTools;
using Fluxor.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;

Expand All @@ -21,10 +22,12 @@ public static FluxorOptions UseReduxDevTools(
updateReduxOptions?.Invoke(reduxOptions);

options.AddMiddleware<ReduxDevToolsMiddleware>();
options.Services.AddScoped<ReduxDevToolsInterop>();
options.Services.AddScoped(_ => reduxOptions);
options.Services.Add<ReduxDevToolsInterop>(options);
options.Services.Add(_ => reduxOptions, options);
options.UseRouting();
return options;
}

}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Fluxor.Blazor.Web.ReduxDevTools.Serialization;
using Fluxor.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Newtonsoft.Json;
using System;
using System.Text.Json;
Expand Down Expand Up @@ -63,7 +63,7 @@ public ReduxDevToolsMiddlewareOptions(FluxorOptions fluxorOptions)
#endif
public ReduxDevToolsMiddlewareOptions EnableStackTrace(
int limit = 0,
string stackTraceFilterExpression =
string stackTraceFilterExpression =
@"^(?:(?!\b" +
@"System" +
@"|Microsoft" +
Expand Down Expand Up @@ -91,7 +91,7 @@ public ReduxDevToolsMiddlewareOptions UseNewtonsoftJson(
JsonSerializerSettings settings = getSettings?.Invoke(sp);
return new NewtonsoftJsonAdapter(settings);
});
FluxorOptions.Services.AddScoped<IJsonSerialization, NewtonsoftJsonAdapter>(implementationFactory);
FluxorOptions.Services.Add<IJsonSerialization, NewtonsoftJsonAdapter>(implementationFactory, FluxorOptions);
return this;
}

Expand All @@ -108,7 +108,7 @@ public ReduxDevToolsMiddlewareOptions UseSystemTextJson(
JsonSerializerOptions jsonOptions = getOptions?.Invoke(sp);
return new SystemTextJsonAdapter(jsonOptions);
});
FluxorOptions.Services.AddScoped<IJsonSerialization, SystemTextJsonAdapter>(implementationFactory);
FluxorOptions.Services.Add<IJsonSerialization, SystemTextJsonAdapter>(implementationFactory, FluxorOptions);
return this;
}
}
Expand Down
36 changes: 34 additions & 2 deletions Source/Fluxor/DependencyInjection/FluxorOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -14,6 +15,8 @@ public class FluxorOptions
internal AssemblyScanSettings[] AssembliesToScan { get; private set; } = Array.Empty<AssemblyScanSettings>();
internal Type[] TypesToScan { get; private set; } = Array.Empty<Type>();
internal Type[] MiddlewareTypes = Array.Empty<Type>();
internal StoreLifetime StoreLifetime { get; set; } = StoreLifetime.Scoped;

/// <summary>
/// Service collection for registering services
/// </summary>
Expand Down Expand Up @@ -53,6 +56,35 @@ public FluxorOptions ScanTypes(
return this;
}

/// <summary>
/// The Store Lifetime that should be used when registering Fluxor features/reducers/effects/middleware
/// </summary>
/// <param name="lifecycle">the lifecycle to use</param>
/// <returns>Options</returns>
/// <remarks>
/// <list type="bullet">
/// <item>
/// <term>LifecycleEnum.Scoped</term>
/// <description>(default) Create a new instance for each new request</description>
/// </item>
/// <item>
/// <term>LifecycleEnum.Singleton</term>
/// <description>Create a new instance on first request and reuse for rest of application lifetime</description>
/// <para>
/// NOTE: indicating Singleton should be done only for exceptional cases.
/// For example, in MAUI/Blazor hybrid applications, the main MAUI application is a different scope then each BlazorWebView component
/// and state needs to be shared across all scopes of the application
/// </para>
/// <para>
/// This value should only be set once during the configuration of Fluxor
/// </para>
/// </remarks>
public FluxorOptions WithServiceLifetime(StoreLifetime lifecycle)
bradtwurst marked this conversation as resolved.
Show resolved Hide resolved
{
StoreLifetime = lifecycle;
return this;
}

/// <summary>
/// Enables automatic discovery of features/effects/reducers
/// </summary>
Expand Down Expand Up @@ -89,7 +121,7 @@ public FluxorOptions AddMiddleware<TMiddleware>()
if (Array.IndexOf(MiddlewareTypes, typeof(TMiddleware)) > -1)
return this;

Services.AddScoped(typeof(TMiddleware));
Services.Add(typeof(TMiddleware), this);
Assembly assembly = typeof(TMiddleware).Assembly;
string @namespace = typeof(TMiddleware).Namespace;

Expand Down
8 changes: 8 additions & 0 deletions Source/Fluxor/DependencyInjection/LifecycleEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Fluxor
{
public enum StoreLifetime
{
Scoped,
Singleton
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Fluxor.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -31,7 +32,7 @@ public static IServiceCollection AddFluxor(

// Register all middleware types with dependency injection
foreach (Type middlewareType in options.MiddlewareTypes)
services.AddScoped(middlewareType);
services.Add(middlewareType, options);

IEnumerable<AssemblyScanSettings> scanIncludeList = options.MiddlewareTypes
.Select(t => new AssemblyScanSettings(t.Assembly, t.Namespace));
Expand All @@ -42,10 +43,11 @@ public static IServiceCollection AddFluxor(
assembliesToScan: options.AssembliesToScan,
typesToScan: options.TypesToScan,
scanIncludeList: scanIncludeList);
services.AddScoped(typeof(IState<>), typeof(State<>));
services.Add(typeof(IState<>), typeof(State<>), options);
services.AddTransient(typeof(IStateSelection<,>), typeof(StateSelection<,>));

return services;
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;

namespace Fluxor.DependencyInjection.ServiceRegistration
Expand All @@ -7,10 +8,11 @@ internal static class EffectClassRegistration
{
public static void Register(
IServiceCollection services,
IEnumerable<EffectClassInfo> effectClassInfos)
IEnumerable<EffectClassInfo> effectClassInfos,
FluxorOptions options)
bradtwurst marked this conversation as resolved.
Show resolved Hide resolved
{
foreach (EffectClassInfo effectClassInfo in effectClassInfos)
services.AddScoped(effectClassInfo.ImplementingType);
services.Add(effectClassInfo.ImplementingType, options);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,7 +10,8 @@ internal static class EffectMethodRegistration
{
public static void Register(
IServiceCollection services,
EffectMethodInfo[] effectMethodInfos)
EffectMethodInfo[] effectMethodInfos,
FluxorOptions options)
{
IEnumerable<Type> hostClassTypes =
effectMethodInfos
Expand All @@ -18,7 +20,7 @@ public static void Register(
.Distinct();

foreach (Type hostClassType in hostClassTypes)
services.AddScoped(hostClassType);
services.Add(hostClassType, options);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Fluxor.DependencyInjection.WrapperFactories;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
Expand All @@ -14,7 +15,8 @@ public static void Register(
FeatureClassInfo[] featureClassInfos,
FeatureStateInfo[] featureStateInfos,
ReducerClassInfo[] reducerClassInfos,
ReducerMethodInfo[] reducerMethodInfos)
ReducerMethodInfo[] reducerMethodInfos,
FluxorOptions options)
{
Dictionary<Type, IGrouping<Type, ReducerClassInfo>> reducerClassInfoByStateType =
reducerClassInfos
Expand All @@ -30,16 +32,18 @@ public static void Register(
services,
featureClassInfos,
reducerClassInfoByStateType,
reducerMethodInfoByStateType);
reducerMethodInfoByStateType,
options);

RegisterStateInfos(
services,
featureStateInfos,
reducerClassInfoByStateType,
reducerMethodInfoByStateType);
reducerMethodInfoByStateType,
options);
}

private static void RegisterFeatureClassInfos(IServiceCollection services, FeatureClassInfo[] featureClassInfos, Dictionary<Type, IGrouping<Type, ReducerClassInfo>> reducerClassInfoByStateType, Dictionary<Type, IGrouping<Type, ReducerMethodInfo>> reducerMethodInfoByStateType)
private static void RegisterFeatureClassInfos(IServiceCollection services, FeatureClassInfo[] featureClassInfos, Dictionary<Type, IGrouping<Type, ReducerClassInfo>> reducerClassInfoByStateType, Dictionary<Type, IGrouping<Type, ReducerMethodInfo>> reducerMethodInfoByStateType, FluxorOptions options)
{
foreach (FeatureClassInfo info in featureClassInfos)
{
Expand All @@ -52,10 +56,10 @@ private static void RegisterFeatureClassInfos(IServiceCollection services, Featu
out IGrouping<Type, ReducerMethodInfo> reducerMethodInfosForStateType);

// Register the implementing type so we can get an instance from the service provider
services.AddScoped(info.ImplementingType);
services.Add(info.ImplementingType, options);

// Register a factory for the feature's interface
services.AddScoped(info.FeatureInterfaceGenericType, serviceProvider =>
services.Add(info.FeatureInterfaceGenericType, serviceProvider =>
{
// Create an instance of the implementing type
var featureInstance =
Expand All @@ -68,7 +72,8 @@ private static void RegisterFeatureClassInfos(IServiceCollection services, Featu
reducerMethodInfosForStateType);

return featureInstance;
});
},
options);
}
}

Expand All @@ -85,7 +90,8 @@ private static void RegisterStateInfos(
IServiceCollection services,
FeatureStateInfo[] featureStateInfos,
Dictionary<Type, IGrouping<Type, ReducerClassInfo>> reducerClassInfoByStateType,
Dictionary<Type, IGrouping<Type, ReducerMethodInfo>> reducerMethodInfoByStateType)
Dictionary<Type, IGrouping<Type, ReducerMethodInfo>> reducerMethodInfoByStateType,
FluxorOptions options)
{
foreach (FeatureStateInfo info in featureStateInfos)
{
Expand All @@ -98,7 +104,7 @@ private static void RegisterStateInfos(
out IGrouping<Type, ReducerMethodInfo> reducerMethodInfosForStateType);

// Register a factory for the feature's interface
services.AddScoped(info.FeatureInterfaceGenericType, serviceProvider =>
services.Add(info.FeatureInterfaceGenericType, serviceProvider =>
{
// Create an instance of the implementing type
ConstructorInfo featureConstructor =
Expand All @@ -115,7 +121,8 @@ private static void RegisterStateInfos(
reducerMethodInfosForStateType);

return featureInstance;
});
},
options);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;

namespace Fluxor.DependencyInjection.ServiceRegistration
{
internal static class ReducerClassRegistration
{
public static void Register(
IServiceCollection services,
ReducerClassInfo[] reducerClassInfos)
ReducerClassInfo[] reducerClassInfos,
FluxorOptions options)
{
foreach (ReducerClassInfo reducerClassInfo in reducerClassInfos)
services.AddScoped(serviceType: reducerClassInfo.ImplementingType);
services.Add(serviceType: reducerClassInfo.ImplementingType, options: options);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,7 +10,8 @@ internal static class ReducerMethodRegistration
{
public static void Register(
IServiceCollection services,
ReducerMethodInfo[] reducerMethodInfos)
ReducerMethodInfo[] reducerMethodInfos,
FluxorOptions options)
{
IEnumerable<Type> hostClassTypes =
reducerMethodInfos
Expand All @@ -18,7 +20,7 @@ public static void Register(
.Distinct();

foreach (Type hostClassType in hostClassTypes)
services.AddScoped(hostClassType);
services.Add(hostClassType, options);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Fluxor.DependencyInjection.WrapperFactories;
using Fluxor.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
Expand All @@ -23,20 +24,21 @@ public static void Register(
featureClassInfos,
featureStateInfos,
reducerClassInfos,
reducerMethodInfos); ;
ReducerClassRegistration.Register(services, reducerClassInfos);
ReducerMethodRegistration.Register(services, reducerMethodInfos);
EffectClassRegistration.Register(services, effectClassInfos);
EffectMethodRegistration.Register(services, effectMethodInfos);
reducerMethodInfos,
options); ;
ReducerClassRegistration.Register(services, reducerClassInfos, options);
ReducerMethodRegistration.Register(services, reducerMethodInfos, options);
EffectClassRegistration.Register(services, effectClassInfos, options);
EffectMethodRegistration.Register(services, effectMethodInfos, options);

services.AddScoped<IDispatcher, Dispatcher>();
services.Add<IDispatcher, Dispatcher>(options);
// Register IActionSubscriber as an alias to Store
services.AddScoped<IActionSubscriber>(serviceProvider => serviceProvider.GetService<Store>());
services.Add<IActionSubscriber>(serviceProvider => serviceProvider.GetService<Store>(), options);
// Register IStore as an alias to Store
services.AddScoped<IStore>(serviceProvider => serviceProvider.GetService<Store>());
services.Add<IStore>(serviceProvider => serviceProvider.GetService<Store>(), options);

// Register a custom factory for building IStore that will inject all effects
services.AddScoped(typeof(Store), serviceProvider =>
services.Add(typeof(Store), serviceProvider =>
{
var dispatcher = serviceProvider.GetService<IDispatcher>();
var store = new Store(dispatcher);
Expand Down Expand Up @@ -71,7 +73,8 @@ public static void Register(
}

return store;
});
},
options);

}
}
Expand Down
Loading