How can I register a specific singleton instance with Caliburn Micro's Simple Container? - caliburn.micro

I've registered a type in Caliburn Micro using it's Simple Container as a singleton.
_container.Singleton<MyType>("MyType");
Now I've realized I need to pass in some specific constructor parameters, so I created an instance of the registered class, configured it, then tried to use RegisterSingleton. And realized it doesn't seem to let me pass a specific instance. I've looked at the docs and don't quite understand how this was supposed to work.
How can I get it to use this specific instance for the singleton?

Call SimpleContainer.RegisterInstance with the service type, key and implementation.
For example:
_container.RegisterInstance(typeof(MyType), "MyType", new MyType());
The simple container is documented here.

Related

how do I access ViewModel inside Work Manager

I'm trying to access ViewModel using hilt inside the worker class which I created but unable to do so, can anyone help please?
You should not try do such a thing in no way. They have totally different lifecycle and one is UI related - the other is not. You should create some other object, like a Singleton, and use it to share the data between the ViewModel and the Work. You can pull the data or use Observer pattern. VM has onCleared method so you can unregister there if you use Observer and observe the data from the VM in the Singleton.

How to provide capability like OnActivate (in Autofac) in Mvx.IoCProvider.Register

Autofac provides the OnActivated() method, which provides the capability to run any action after constructing a registered type.
Is possible to use a similar method in MvvmCross? Do you have any ideas to provide the same functionality?
It usually pays to understand the fundamentals of Dependency Injection (DI) instead of relying on particular DI Container features. Ask yourself the question: If I didn't have a DI Container, then how would I solve my problem?
Ironically, it turns out that things are usually much simpler with Pure DI.
If you didn't have a DI Container, then how would you run an action after construction of an object?
The easiest solution is to provide a factory that creates and initialises the object. Assuming the same API and requirements as the Autofac documentation implies, you could do this:
public static Dependency2 CreateDependency2(ITestOutputHelper output, Dependency1 dependency)
{
var d2 = new Dependency2(ITestOutputHelper output, Dependency1 dependency);
d2.Initialize();
return d2;
}
If you still must use another DI Container, most of them enable you to register a factory like the above against the type. I don't know how MvvmCross works, but I'd be surprised if this wasn't possible. If it isn't, you can implement an Adapter over your actual dependency. The Adapter would take care of running the action on the adapted object.
FWIW, if an object isn't in a valid state before you've run some action on it, then encapsulation is broken. The fundamental characteristic of encapsulation is that objects protect their invariants so that they can never be in invalid states. If possible, consider a better API design.

Hangfire jobs utilising Autofac IoC singletons sharing a interface

I cant seem to find any information about this and hope someone can help.
With a class "TestClass" inheriting ITestClass I can register an Autofac singleton with the following code:
builder.RegisterType<TestClass>().As<ITestClass>().SingleInstance();
Adding a job to Hangfire is just as easy:
RecurringJob.AddOrUpdate<ITestClass>(x => x.MethodInITestClass, Cron.MinuteInterval(1));
What I cant seem to figure out is how to register multiple classes as Autofac singletons all having the same interface and being able to create a Hangfire job for a specific singleton.
For instance, having an interface named ITest and classes TestClass1, TestClass2 and TestClass3 utilising this interface I would like to add a Hangfire job for TestClass2.
I thought maybe named singletons would be a solution which can be created easily:
builder.RegisterType<TestClass1>().Named<ITest>("TestClass1").SingleInstance();
builder.RegisterType<TestClass2>().Named<ITest>("TestClass2").SingleInstance();
builder.RegisterType<TestClass3>().Named<ITest>("TestClass3").SingleInstance();
However, adding a Hangfire job for TestClass2 seems impossible as Hangfire only takes a interface as an argument and the interface now has 3 related singletons.
I would also like to be able to resolve all singletons implementing this interface into a IEnumerable which also seems impossible with named singletons.
Any advice on this? I guess named singletons may be a dead end?
I don't think named or keyed services will help you here. I took a look at the JobActivator implementation and there does not seem to be a way to have the name or key available in the ActivateJob(Type jobType) method where the service is resolved.
However, adding a Hangfire job for TestClass2 seems impossible as Hangfire only takes a interface as an argument and the interface now has 3 related singletons.
I don't think this is correct, so you could use your singleton types (TestClass1, TestClass2, ...) directly when adding a job. To do so you would have to register your singletons AsSelf() as well:
builder.RegisterType<TestClass>().AsSelf().As<ITestClass>().SingleInstance();
You'll still be able to resolve all your singletons using the ITestClass interface. If you don't have access to your singleton types in the code where you are adding the job you'll have to add an interface for each singleton (ITestClass1, ITestClass2, ...) and then use these interfaces for creating the jobs.
Thank you for your answer fknx! :)
I see that by registering like this:
builder.RegisterType<TestClass1>().AsSelf().As<ITestClass>().SingleInstance();
builder.RegisterType<TestClass2>().AsSelf().As<ITestClass>().SingleInstance();
builder.RegisterType<TestClass3>().AsSelf().As<ITestClass>().SingleInstance();
.. would enable me to resolve them all using the ITestClass. What I don't see is how I would be able to register a Hangfirejob for i.e. TestClass2?
Your proposal for solution if I don't have access to singleton types is working great!
Registering:
builder.RegisterType<TestClass1>().As<ITestClass1>().As<ITestClass>().SingleInstance();
builder.RegisterType<TestClass2>().As<ITestClass2>().As<ITestClass>().SingleInstance();
builder.RegisterType<TestClass3>().As<ITestClass3>().As<ITestClass>().SingleInstance();
Also, I have ITestClassX inheriting ITestClass so that if I resolve by ITestClassX or ITestClass I still have access to the same methods.
Adding a Hangfire job:
RecurringJob.AddOrUpdate<ITestClass2>("JobTitle", x => x.DoAJob(), Cron.MinuteInterval(5));

How does ninject work at a high level, how does it intercept object instantiation?

At a high level, how do these dep. injection frameworks work?
I can understand if you always instantiate an object via a custom factory like:
IUser user = DepInjector.Get<User>();
I'm guessing what happens is, wherever you defined the mappings, it will look at the type you want and try and find a match, if found, it will via reflection instantiate the type.
Are there dep. inj. frameworks that would work like:
IUser user = new User();
If so, how would it get the correct user, where is it hooking into the CLR to do this? In case of an asp.net website, is it any different?
If you want to know how Ninject works then the obvious place to start would be reading How Injection Works on their official wiki. It does use reflection but it now also uses dynamic methods:
"By default, the StandardKernel will
create dynamic methods (via
System.Reflection.Emit.DynamicMethod)
that can be used to inject values into
the different injection targets. These
dynamic methods are then triggered via
delegate calls."
As for you second example, I don't believe there are any DI frameworks that would do what you ask. However, constructor injection tends to be most common way of implementing IoC, so that when a class is constructed it knows what type to bind to via some configuration binding. So in your example IUser would be mapped to concrete User in config bindings so that any consuming class that has an IUser parameter as part of its constructor would get the correct User type passed in.
AFAIK there's no way to "hook into" object instantiation with the CLR. The only way to use DI in the second case would be to employ an assembly rewriter (i.e. a postprocessor similar to PostSharp) to replace the call to new with a call to the DI factory method (i.e. GetUser) in the compiled code.

ResolvedParameter in Unity. Can somebody explain to when to use it?

I am sort of new to Unity all seems to be fine but I am kind of lost when to use
ResolvedParameter in Unity.
Googled and looked on MSDN but still cannot understand when to use it.
Do you have a simple example that could illustrate it's use.
Thanks a lot for your help
You may wish to configure a Type with constructor parameters of a resolved service and a string. In this case you would use ResolvedParameter.
Container.RegisterType<IRepository, Repository>(
new InjectionConstructor(
new ResolvedParameter<IClassifier>(),
"ConnectionString"));
It's for method injection; see Entering Configuration Information on MSDN. Scroll down to "Dynamically Configuring Constructor, Property, and Method Injection" and note that the ResolvedParameter is actually a parameter to the InjectionMethod constructor.
I've never encountered a need to use it. Constructor injection will solve 95% of your issues, and property injection will solve the other 5%. (Caveat: I've only used Unity on a couple of projects, so I don't claim to be an expert.)
As I see it its to be used when you have a constructor where at least one parameter can not be obtained from the container while the rest can. In such a situation you declare how to resolve each ctor parameter when actually creating a new instance of that type.
Container.RegisterSingleton<IConnectionManager, ConnectionManager>(new InjectionConstructor(new ResolvedParameter<INetworkClientFactory>(), Container.Resolve<IBackoffAlgorithm>(), 10));
In my example, the IConnectionManager instance obtains the first parameter from the container (via ResolvedParameter), the 2nd one via Container.Resolve<>, and the 3rd one is a hard-coded integer.
ResolvedParameter should behave equal to a direct Container.Resolve<> but looks a tad cleaner.

Resources