Async load settings before static constructor - c#

I was just finishing my new app, but I got stuck. My app is divided into 2 parts - remote and local. What I need is to register a class for interface based on some async deserialized application settings. Here is the 'idea code'
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// It can't work :(((
if(await SettingsManager.LoadSettings().EnableRemote) // <<<<<<
{
SimpleIoc.Default.Register<IMyService, MyRemoteService>();
}
else
{
SimpleIoc.Default.Register<IMyService, MyLocalService>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SomeOtherViewModel>();
}
How could I solve it? The settings are serialized in an XML file in Isolated Storage of my WinRT app. Please, can you think of any suggestions?

It sort of breaks the IoC pattern to register bindings asynchronously. You'll need to incorporate the async settings into a wrapper class. This wrapper class should be responsible for:
loading the settings
providing the actual implementation of IMyService
If IMyService has synchronous methods, then you'll probably have to change it, either to provide async versions of all the methods, or to provide a Ready property + event, so that consumers will know when it is safe to access. But if it's a service, its methods are probably already async, right?
As an illustration, let's call the wrapper class MyServiceWrapper. It will load the settings when it is first constructed, and pass through all asynchronous methods in IMyService (for example, SomeMethodAsync as below).
public interface IMyService
{
Task SomeMethodAsync(Action<bool> callback);
}
public class MyServiceWrapper : IMyService
{
private IMyService _impl = null;
private IMyService _remote, _local;
private bool _loaded = false;
private object _sync = new object();
public Task SomeMethodAsync(Action<bool> callback)
{
// first make sure the settings have been loaded
await LoadSettings();
_impl.SomeMethodAsync(callback);
}
public MyServiceWrapper(MyRemoteService remoteService, MyLocalService localService)
{
_remote = remoteService;
_local = localService;
LoadSettings();
}
private async Task<bool> LoadSettings()
{
if (_loaded)
return true;
// lock to prevent multiple threads from loading the settings
lock (_sync)
{
if (_loaded)
return true;
if(await SettingsManager.LoadSettings().EnableRemote)
_impl = _remote;
else
_impl = _local;
}
return true;
}
}
Now you can have your DI container register:
MyRemoteService -> MyRemoteService
MyLocalService -> MyLocalService
IMyService -> MyServiceWrapper

Related

Simple Injector dynamic context-based injection at runtime between two registrations

I have a Mediator application using Simple Injector for command handler registration, and injection and handlers is all setup and working perfectly.
class DoWashingCommandHandler : IRequestHandler<DoWashingCommand,object>
{
IBus bus;
public DoWashingCommandHandler(IBus bus) { this.bus = bus; }
Task<object> Handle(DoWashingCommand command)
{
this.bus.Send(new OtheCommand());
}
}
I have a need for 2 registrations of a IBus implementations.
The first can be of any lifetime, the second has a background thread so i initially thought it would need to be a singleton but on review i believe it could also be of any lifetime and just have a static worker thread class within it (this would be important for scope):
// register as non-singleton to allow scope usage
// keep static worker thread as if it were Singleton
class DispatchOnBackgroundThread : IBus
{
static Worker = new Worker();
public Task<object> Send(object command)
{
Worker.Post(command);
}
public void Start(Container container, CancelationToken stoppingToken)
{
Worker.Start(container,stoppingToken);
}
class Worker
{
public void Post(object command) { /* snip */ }
public void Start(Container container, CancelationToken stoppingToken)
{ /* snip */ }
public void Thread()
{
/* loop */
var item = ReadFromQueue();
// get command handler type
// get command handler instance from container
// if instantiated instance has IBus dependency in this
// section then it must have used DispatchInThread as the
// concrete implementation for IBus (including if the handler
// calls container.GetInstance<IBus>()
handler.Handle(item.Request, cancellationToken);
}
// anything outside this Thread should use
// DispatchOnBackgroundThread for IBus
}
}
Then the registrations would be as follows (not sure how to avoid the double registration issue of IBus):
// i need to be able to register two types
container.Register<IBus,DispatchOnBackgroundThread>();
container.Register<IBus,DispatchInThread>();
// this would return any IBus references with DispatchOnBackgroundThread
var handler = this.container.GetInstance(requestHandlerType);
using(SomeSope.BeingScope(container))
{
// this would return any IBus references with DispatchInThread
var handler = this.container.GetInstance(requestHandlerType);
// and if handler or other code referenced container and called
// GetInstance, and IBus dependencies would be returned as
// DispatchInThread whilst in this scope
}
// this would return any IBus references with DispatchOnBackgroundThread
var other = this.container.GetInstance(requestHandlerType);
I think and in summary, this is a mix of Context-based injection and custom scope.
How can I achieve the above or is this a terrible code smell?
To give further context if required I need the above switchable resolved types in order to implement the solution of another question https://stackoverflow.com/a/61782405/915839
DI code is removed in above link, but i am very much using SimpleInjector in the actual implementation
I'm not sure I fully understand your use case, and what it is that leads to this, but what you can do is create a wrapper IBus implementation that forwards the call to the correct bus, while changing the forwarded bus implementation while running on a background thread.
This wrapper might look as follows:
class SwitchableBus : IBus
{
private readonly DispatchInCallingThread defaultBus;
private readonly DispatchOnBackgroundThread backgroundBus;
public SwitchableBus(
DispatchInCallingThread defaultBus, DispatchOnBackgroundThread backgroundBus)
{
this.defaultBus = defaultBus;
this.backgroundBus = backgroundBus;
this.Bus = defaultBus;
}
public IBus Bus { get; private set; }
public void SwitchToBackgroundBus() => this.Bus = this.backgroundBus;
public Task<object> Send(object command) => this.Bus.Send(command);
}
With this wrapper, you can use the following registrations:
container.Register<IBus, SwitchableBus>(Lifestyle.Scoped);
container.Register<SwitchableBus>(Lifestyle.Scoped);
container.Register<DispatchInCallingThread>(Lifestyle.Scoped);
container.Register<DispatchOnBackgroundThread>(Lifestyle.Scoped);
This allows you to have DispatchInCallingThread used in the graph as follows:
using(SomeSope.BeingScope(container))
{
var handler = this.container.GetInstance(requestHandlerType);
handler.Handle(request);
}
In other words, by default the DispatchInCallingThread is used.
And DispatchOnBackgroundThread can be used by the graph as follows:
using(SomeSope.BeingScope(container))
{
container.GetInstance<SwitchableBus>().SwitchToBackgroundBus();
var handler = this.container.GetInstance(requestHandlerType);
handler.Handle(request);
}
Concequence of this is, however, that you should always resolve within an active Scope. But that would be a good idea anyway, because it is likely there will be Scoped dependencies in a graph anyway. Simple Injector does not allow resolving a graph with Scoped dependencies outside the context of an active scope.

Event dispatching library with IoC

In the past I've built a MessageDispatcher component that scans an assembly for types decorated with certain attributes and initializes an instance of each. Then, when any object is fed to the MessageDispatcher instance, every previously initialized instance which contains a method which signature contains the type of the passed object has said method triggered with the specified parameter. For example, in a scenario like:
[Listener]
public class MyListener
{
MessageDispatcher _dispatcher; //Assigned elsewhere
[MessageListener]
public async Task DoSomething(int value)
{
var otherValue = await _dispatcher.Next<string>();
Console.WriteLine($"{value} is {otherValue}.");
}
}
The following code initializes an instance of the MyListener class, calls DoSomething and prints "7 is okay.":
var listener = new MessageDispatcher(typeof (ListenerAttribute));
listener.Dispatch(7);
listener.Dispatch("okay");
I would like to know if there are any libraries out there that are dedicated to or include a service like such. It has to be able to:
Scan assemblies and initialize types based on an attribute.
Dynamically "subscribe" to certain types
"Wait" on a value to be pumped from the dispatcher (like with the Next method in my example).
(as library recommendations is not allowed per the SO rules, here is an attempt to instead answer with an implementation)
You can get that with virtually any IoC. All they need is to be able to register services using an attribute or some other conventional way.
As for the message dispatching. Just create an interface like IMessageHandler<TMessage>. Implement it on all classes that should handle messages.
Example:
public interface IMessageHandler<TMessage>
{
void Handle(TMessage msg);
}
public class SomeService : IMessageHandler<UserCreated>
{
//[.. all other methods ..]
public void Handle(UserCreated msg)
{
// ...
}
}
To publish messages you create a dispatcher. Since you use a container you do not have to make it static. Use your container inside it (service location) to dispatch the messages. Now some peeps might say oohh no, service location is anti-pattern, buhuhuhu. Well no. Not in all cases. In this case it's an implementation details in a class with the specific purpose to identify and invoke other classes.
public interface IMessageDispatcher
{
void Dispatch<TMessage>(TMessage msg);
}
// The actual implementation differs
// depending on your choice of container.
public class ContainerBasedMessageDispatcher : IMessageDispatcher
{
Container _container;
public ContainerBasedMessageDispatcher(Container container)
{
_container = container;
}
public void Dispatch<TMessage>(TMessage message)
{
using (var scope = container.BeginLifetimeScope())
{
var handlers = scope.Resolve<IEnumerable<IMessageHandler<TMessage>>();
foreach (var handler in handlers)
{
handler.Handle(message);
}
}
}
}
The code is written directly in SO. So it might not work as-is. But hopefully it's given you an idea how to achieve what you want.
Usage:
public class UserService
{
IMessageDispatcher _dispatcher;
public UserService(IMessageDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void Create(User user)
{
//[...]
_dispatcher.Dispatch(new UserCreated(user.Id));
}
}
this do however not dynamically allow you to subscribe on what you want. If just ignoring unwanted messages is not feasible. Then this answer is not for you.

How to unit test decorator registrations using SimpleInjector 3+?

Follow up to an older question here. Say I have a registration like the following:
container.Register(typeof(IHandleCommand<>), _handlerAssemblies, Lifestyle.Transient);
container.RegisterDecorator(typeof(IHandleCommand<>),
typeof(MetricsCommandHandlerWrapper<>), Lifestyle.Singleton);
Where the MetricsCommandHandlerWrapper is defined like so:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T> where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory)
{
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public async Task HandleAsync(T command)
{
// code to record metrics around command handling which eventually invokes
await _handlerFactory().HandleAsync(command).ConfigureAwait(false);
}
}
How can I write a unit test that asserts the actual decoratee handlers are registered with Transient lifestyle?
I have tried composing the root and inspecting the registration for a closed IHandleCommand<FakeCommand> type, which reveals an ImplementationType of MetricsCommandHandlerWrapper<FakeCommand> as expected. Invoking GetRelationships() on that registration reveals its 2 dependencies, ICollectMetrics and the one I am interested in, the Func<IHandleCommand<FakeCommand>> factory delegate, which is registered as a Singleton. However invoking .Dependency.GetInstance() on that factory delegate throws an exception that the instance producer returned null.
Is there any way to assert that the inner decoratee is registered as Transient, and if so, how?
The use of the Func<T> delays the building of the object graph, and from perspective of the diagnostic system, the graphs stops at that point. So, it's not possible to do this analysis.
Instead of completely relying on Simple Injector's internals however, you can also choose to make some minor changing in your application to allow testing decorators.
What you can do is implement an IDecorator abstraction on your decorators:
public interface IDecorator {
object Decoratee { get; }
}
Now each decorator can implement this interface. For the MetricsCommandHandlerWrapper<T>, it might look as follows:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T>, IDecorator where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory) {
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public object Decoratee { get { return _handlerFactory(); }
public async Task HandleAsync(T command) { ... }
}
On top of the IDecorator interface, you can define a simple extension method:
public static IEnumerable<Type> GetDecoratorChain(this IDecorator decorator) {
while (decorator != null) {
yield return decorator.GetType();
decorator = decorator.Decoratee as IDecorator;
}
}
Inside your unit test you can now resolve a handler and ask for the list of applied decorators. Using this list you can verify whether decorators are applied in the correct order.

Forcing a syncronous reactive extension call

I am working on some code which looks something like this:
public class ManagerViewModel : ManagerViewModelBase
{
public ManagerViewModel(ISettingsProvider settingsProvider):
base(settingsProvider.Settings)
}
public class ManagerViewModelBase
{
private IEnumerable<string> _mySettings = Enumerable.Empty<string>();
public ManagerViewModelBase(IEnumerable<string> settings)
{
_mySettings = settings;
}
}
ISettingsProvider is provided via Unity and looks like:
public class SettingsProvider : ISettingsProvider
{
private readonly Service _service;
IEnumerable<string> _settings = Enumerable.Empty<string>();
public IEnumerable<string> Settings {get {return _settings}};
public SettingsProvider (
IService _service,
ISettingsProvider settingsProvider)
{
_service = service;
LoadSettings();
}
private void LoadSettings()
{
//_service just supplies the data
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}
private void LoadSettingsCompleted(IEnumerable<string> settings)
{
_settings = settings;
}
}
The issue is that when SettingsProvider is instantiated, it may take a little time to get the results from the service call and as a result, before the call is completed and _settings populated, the base(settingsProvider.Settings) call is made, basically passing on an empty enumerable.
Is there a way I can make the SettingsProvider.Settings property call wait until the data from the Service.GetSettings call is available, and timeout after a certain amount of time? I guess I am looking for the simplest way to block on that property call.
Thanks.
I realized your question is how to wait/block, but I must tell you that you probably shouldn't. Likely your ViewModel is getting created in the UI thread, and blocking is the last thing you want in there.
If your ViewModel relies on something asynchronous, then its creation is asynchronous, and you should hide that with the wait.
Async in constructor can't be used, but alternatively you can make your VM constructor private, and expose an async static factory method instead, something like:
private ManagerViewModel(IEnumerable<string> settings) : base(settings) {}
public async Task<ManagerViewModel> CreateAsync(ISettingsProvider settingsProvider) {
var settings = await settingsProvider.GetSettingsAsync();
return new ManagerViewModel(settings);
}
// ....
public async Task<IEnumerable<Settings>> GetSettingsAsync() {
return await _service.GetSettings().Timeout(...).FirstAsync();
}
Expose async all the way and never block would be my recommandation.
None of this is very reactive but you could block using the Observable.FirstAsync() and Observable.Wait() extension methods. So your LoadSettings() method could look something like:
private void LoadSettings()
{
_settings = _service.GetSettings
.Timeout(_expireTime, Observable.Return(Enumerable.Empty<string>()))
.FirstAsync()
.Wait();
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}

WCF: Make all calls wait when one specific interface is being called

I have a WCF service with quite a few interfaces which only read data. There is however one interface that reloads data from the database and reinitialises some dictionaries. While this interface "Reload" is running I effectively want all other calls to be put "on hold" as they would read data of an unknown state (as I am using per-call)
[ServiceContract]
public interface IMyObject
{
[OperationContract]
string Reload();
[OperationContract]
string Read1();
[OperationContract]
string Read2();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class MyObject : IMyObject
{
public string Reload() { //Takes 5-10secs, called twice a day }
public string Read1() { //Wait for Reload() to finish if it's running}
public string Read2() { //Wait for Reload() to finish if it's running}
}
Is this possible in WCF? Or is there a best practise way around this problem?
I believe if you play with the ConcurrencyMode and set it to single you can achieve what you want.
Having said that, I had achieved what you want having a flag on my services. If you set a static flag other calls can check for that flag and do what ever you want them to do
Suggest you to:
Change InstanceContextMode.PerCall to InstanceContextMode.Single
Then add ConcurrencyMode = ConcurrencyMode.Multiple (will allow more than 1 execution in a time)
In your MyObject implementation manually deal with concurrency. Use simple lock or advanced mechanics, like ReaderWriterLockSlim.
Implementation with lock is as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
class MyObject: IMyObject
{
private readonly object lockObject = new object();
public string Reload()
{
lock (lockObject)
{
// Reload stuff
}
}
public string Read1()
{
lock (lockObject)
{
// Read1 stuff
}
}
public string Read2()
{
lock (lockObject)
{
// Read2 stuff
}
}
}
Drawbacks, that it won't allow you to call simultaneously Read1 and Read2. If you need this functionality, use ReaderWriterLockSlim instead of lock.

Categories

Resources