Autofac - dynamic Resolve based on registered provider - autofac

I'm having problems finding proper solution for my problem, namely:
Let's consider workflow:
Application starts
Main components are registered in Autofac
Application loads plugin assembly and registers modules within it
Container is being build
Plugin handling logic is run
Plugin can add its own controllers. To properly handle that I had to prepare interface which will provide me types of custom controllers:
interface ICustomControllerProvider
{
IEnumerable<Type> GetControllerTypes();
}
Based on the above my app knows how to integrate specified types as controllers.
All controllers are also defined as services, so Autofac deals with their creation, and so...
Problem:
I want to avoid specifying custom controller type twice
public PluginControllerProvider : ICustomControllerProvider
{
public IEnumerable<Type> GetControllerTypes()
{
// 1st type specification
// controller types are specified here, so they could be integrated with app
yield return typeof(ControllerX);
yield return typeof(ControllerY);
}
}
public class PluginModule : Module
{
protected override void Load(ContainerBuilder builder)
    {
builder.RegisterType<PluginControllerProvider>().As<ICustomControllerProvider>();
// 2nd type specification
// controllers have to be register in module as well
builder.RegisterType<ControllerX>();
builder.RegisterType<ControllerY>();
}
}
Is there any way how ControllerX and ControllerY could be managed by Autofac, where I specified them only in PluginControllerProvider?
I tried achieving that by providing custom registration source and resolving ICustomControllerProvider, however I cannot resolve ICustomControllerProvider based on arguments provided by IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<ServiceRegistration>> registrationAccessor) from IRegistrationSource

Autofac does not offer the ability to inject a list of types registered with Autofac. You'll have to get that yourself by working with the lifetime scope registry.
Before I get into how you might solve this, I should probably note:
Listing the types registered is not a normal thing from a DI perspective. It'd be like listing all the controllers in your MVC application - you don't normally need to do that, and if you did, you'd likely need to build a whole metadata structure on top of it like the ApiExplorer that was built to do that on top of ASP.NET Core. That structure wouldn't be supported or involved with the DI system because you're querying about the system, not injecting live instances into the system.
If you are relying on DI to resolve controllers, you probably don't need a whole separate controller provider. Once you know what type you need for the request, you'd just resolve it.
All that's to say, while I'll answer the question, the way the design here is posed may be something you'd want to look at. What you're doing, trying to involve DI with listing metadata about the app... seems somewhat backwards (you'd feed the DI container based on the list of types, not get the list of types from the DI container).
But let's just go with it. Given:
There are controllers registered with Autofac
The controllers have no common base class or interface
There's no attributes on the controllers you could query
What I'd do is register all the controllers with some metadata. You need something to be able to locate the controllers in the list of all the types in the container.
builder.RegisterType<ControllerX>().WithMetadata("controller", true);
builder.RegisterType<ControllerY>().WithMetadata("controller", true);
Now in the plugin controller, you need to inject an ILifetimeScope because you have to query the list of stuff registered. The ILifetimeScope that gets injected into the controller will be the same scope from which the plugin controller itself was resolved.
You can use the injected scope to query things in the component registry tagged with your metadata.
public class PluginControllerProvider : ICustomControllerProvider
{
private readonly Type[] _controllerTypes;
public PluginController(ILifetimeScope scope)
{
_controllerTypes = scope
.ComponentRegistry
.Registrations
.Where(r => r.Metadata.ContainsKey("controller"))
.Select(r => r.Activator.LimitType)
.ToArray();
}
public IEnumerable<Type> GetControllerTypes()
{
return _controllerTypes;
}
}
Now, disclaimers:
If you are registering more controllers in child lifetime scopes (e.g., during a BeginLifetimeScope() call), you will need a controller provider from that scope or it won't get all the controller types. The provider needs to come from the scope that has all the registrations.
If you're using registration sources (like the AnyConcreteTypeNotAlreadyRegisteredSource), this won't capture things that come from the registration sources. It'll only capture things that come from direct registrations of a type (or lambda) on a ContainerBuilder.
But it should work.

Related

Is it possible to implement a module that is not a WPF module (a standard class library, no screens)?

I am developing a modular WPF application with Prism in .Net Core 5.0 (using MVVM, DryIoc) and I would like to have a module that is not a WPF module, i.e., a module with functionality that can be used by any other module. I don't want any project reference, because I want to keep the loosely coupled idea of the modules.
My first question is: is it conceptually correct? Or is it mandatory that a module has a screen? I guess it should be ok.
The second and more important (for me) is, what would be the best way to create the instance?
This is the project (I know I should review the names in this project):
HotfixSearcher is the main class, the one I need to get instantiated. In this class, for example, I subscribe to some events.
And this is the class that implements the IModule interface (the module class):
namespace SearchHotfix.Library
{
public class HotfixSearcherModule : IModule
{
public HotfixSearcherModule()
{
}
public void OnInitialized(IContainerProvider containerProvider)
{
//Create Searcher instance
var searcher = containerProvider.Resolve<IHotfixSearcher>();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IHotfixSearcher, HotfixSearcher>();
}
}
}
That is the only way I found to get the class instantiated, but I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
For modules that have screens, the instances get created when navigating to them using the RequestNavigate method:
_regionManager.RequestNavigate(RegionNames.ContentRegion, "ContentView");
But since this is only a library with no screens, I can't find any other way to get this instantiated.
According to Prism documentation, subscribing to an event shoud be enough but I tried doing that from within my main class HotfixSearcher but it does not work (breakpoints on constructor or on the event handler of the event to which I subscribe are never hit).
When I do this way, instead, the instance is created, I hit the constructor breakpoint, and obviously the instance is subscribed to the event since it is done in the constructor.
To sum up, is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
Thanks in advance!
Or is it mandatory that a module has a screen?
No, of course not, modules have nothing to do with views or view models. They are just a set of registrations with the container.
what would be the best way to create the instance?
Let the container do the work. Normally, you have (at least) one assembly that only contains public interfaces (and the associated enums), but no modules. You reference that from the module and register the module's implementations of the relevant interfaces withing the module's Initialize method. Some other module (or the main app) can then have classes that get the interfaces as constructor parameters, and the container will resolve (i.e. create) the concrete types registered in the module, although they are internal or even private and completely unknown outside the module.
This is as loose a coupling as it gets if you don't want to sacrifice strong typing.
is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
You can skip the var searcher = part :-) But if the HotfixSearcher is never injected anywhere, it won't be created unless you do it yourself. OnInitialized is the perfect spot for this, because it runs after all modules had their chance to RegisterTypes so all dependencies should be registered.
If HotfixSearcher is not meant to be injected, you can also drop IHotfixSearcher and resolve HotfixSearcher directly:
public void OnInitialized(IContainerProvider containerProvider)
{
containerProvider.Resolve<HotfixSearcher>();
}
I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
It is used, I suppose, although not through calling one of its methods. It's used by sending it an event. That's just fine. Think of it like Task.Run - it's fine for the task to exist in seeming isolation, too.

How to create a library exposing named configured singletons generated at runtime with Dagger 2?

I'm considering migrating to Dagger 2 some libraries. This library expose a configurable client, each configuration can be named and later retrieved in a singleton fashion.
Let me show a pseudo-code of how the library works from the user perspective:
// initialization
ClientSDK clientA = new ClientSDK.Builder()
.configuration().attributes().here()
.apiKey("someString") // set api key / credentials
.build();
LibraryAuthenticationManager customAuthManager = new MyCustomAuthenticationManager();
ClientSDK clientB = new ClientSDK.Builder()
.configuration().attributes().here()
.apiKey("someStringElse")
.customAuthManager(customAuthManager) // override some default
.baseApiUrl("https://custom.domain.com/and/path") // override some default setting
.build();
ClientSDK.setSingleton("clientA", clientA);
ClientSDK.setSingleton("clientB", clientB);
And when I need an instance elsewhere:
// usage everywhere else
ClientSDK clientB = ClientSDK.singleton("clientB");
clientB.userManager(); // "singleton" using the configuration of clientB
clientB.subscriptionsManager(); // "singleton" using the configuration of clientB
clientB.currentCachedUser(); // for clientB
clientB.doSomething(); // action on this instance of the ClientSDK
ClientSDK instances are created by the user of the library and the ClientSDK statically keep a map of singletons associated to the name.
(The actual behavior of the SDK is slightly different: the naming is automatic and based on a mandatory configuration parameter.)
It's like I have lot of singleton classes with a single point of entry (the ClientSDK) but since I can have multiple configuration of the ClientSDK each with his own singletons instances this are not really singletons.
If I would try write a library like that with Dagger 2 I would do something like:
class ClientSDK {
#Inject SDKConfiguration configuration;
#Inject LibraryAuthenticationManager authManager;
...
}
The problem is that I need each instance of the ClientSDK to have its own configuration and authManager (and many other services) injected. And they need to be definable (the configuration) and overridable (the actual implementation) from the library user.
Can I do something like this with Dagger 2? How?
I've seen I can create custom Scopes but they are defined at compile time and the library user should be the one defining them.
(the library is an Android Library, but this shouldn't be relevant)
Thanks
It sounds like you should be creating stateful/configurable Module instances and then generating separate Components or Subcomponents for each ClientSDK you build.
public class ClientSDK {
#Inject SDKConfiguration configuration;
#Inject LibraryAuthenticationManager authManager;
// ...
public static class Builder {
// ...
public ClientSDK build() {
return DaggerClientSDKComponent.builder()
.configurationModule(new ConfigurationModule(
apiKey, customAuthManager, baseApiUrl)
.build()
.getClientSdk();
}
}
}
...where your ConfigurationModule is a #Module you write that takes all of those configuration parameters and makes them accessible through properly-qualified #Provides methods, your ClientSDKComponent is a #Component you define that refers to the ConfigurationModule (among others) and defines a #Component.Builder inner interface. The Builder is important because you're telling Dagger it can no longer use its modules statically, or through instances it creates itself: You have to call a constructor or otherwise procure an instance, which the Component can then consume to provide instances.
Dagger won't get into the business of saving your named singletons, but it doesn't need to: you can save them yourself in a static Map, or save the ClientSDKComponent instance as an entry point. For that matter, if you're comfortable letting go of some of the control of ClientSDK, you could even make ClientSDK itself the Component; however, I'd advise against it, because you'll have less control of the static methods you want, and will lose the opportunity to write arbitrary methods or throw exceptions as needed.
You don't have to worry yourself about scopes, unless you want to: Dagger 2 tracks scope lifetime via component instance lifetime, so scopes are very easy to add for clarity but are not strictly necessary if you're comfortable with "unscoped" objects. If you have an object graph of true singleton objects, you can also store that component as a conventional (static final field) singleton and generate your ClientSDKComponent as a subcomponent of that longer-lived component. If it's important to your build dependency graph, you can also phrase it the other way, and have your ClientSDKComponent as a standalone component that depends on another #Component.

Castle Windsor Lifestyle configuration

I've spent some time looking around, and there doesn't seem to be an obvious solution to this scenario.
I register all types from an assembly (that's about 80 types, interfaces are in separate assembly)
public static void RegisterAllFromAssemblies(string a)
{
IoC.Container.Register(
AllTypes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);
}
now say if i want to use a different LifeStyle for one of those objects, i can't override since i'll get the There is a component already registered for the given key error.
i've looked into various ways to modify the lifestyle after this registration, but so far haven't been able to make anything work.
what should be the ideal solution here? i'd prefer not to give up the AllTypes functionality.
i suppose i could specify a .Where filter when registering all and skip a few objects to be registered manually, but that's not a very enterprisey solution..
I believe you're talking about registering all of the types in an assembly where some of the types in the assembly might need to be registered with different lifestyles. So you've got IRepository which needs to be a PerWebRequest and ITypeMapper which can be a singleton.
I clarify because you could also mean that you want to have IRepository be a PerWebRequest at one spot in your code and a singleton in another spot. Without creating crazy lifestyles, you can create your component and register it for the default lifestyle. If you need another lifestyle sometimes you can create a new component and inherit from the existing one just for use in registration (the code sample shows this if this is confusing).
I wrote the sample so that it will work for either scenario and I gave a couple different approaches all focusing around the filtering abilities of configuring multiple items at once.
For this one, I'm calling out configuration for a particular component by type. It's not as "enerprisey" as you put it, but the intent is clearer if you only have a few exceptions to the rule. You'll note you can chain together configures. The unless is required because the second configure will pick up the component for the first configure being that my only condition is the services are based on IService. This assumes that castle processes the configures in order. I believe the assumption is sound, but haven't looked at the source for awhile.
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));
This one uses attributes to more generically deviate from the normal lifestyle "PerWebRequest
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));
Now that I've given you a few samples that solve your immediate issue (as I understand it) let me give you my advice for free!
First I don't really like WithService.FirstInterface(). As the intelisense states it's non-deterministic when you implement multiple interfaces. Any dev could come in and make a harmless interface change to a class and then break the system. If you can get away with WithService.DefaultInterfaces() you'd have a harder to mess up solution. Default interfaces is just telling castle that when registering the Foo component, use the service IFoo if it implements an interface named IFoo.
Second, I believe if you partition your registration logic into cohesive units you probably wouldn't have run into this problem. The key is to have many installer files that implement IWindsorInstaller. Inside of these installers you only register (using the Classes or Types to keep it enterprisey still) types that make sense for the particular installer. The chances that you have multiple lifestyle concerns in the same installer is pretty low (and if you find this, you probably need more installers)
If you followed this approach you could end up with a RepositoryInstaller, ViewInstaller, ControllerInstaller, etc. More on installers can be found on the castle documentation site
What you could do if you wanted is then have a common boostrapper for all your systems that looks into the application directory and installs all of the installers that are in the directory. Being this wasn't what you asked I'll stop elaborating, but if interested you can ping me and I can show you more about what I'm talking about.
Full sample code as a console app:
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultipleLifecyles
{
[AttributeUsage(AttributeTargets.Class)]
public class ShouldBeSingleton : Attribute
{
}
public interface IService
{
void DoSomething();
}
public class MyComponent : IService
{
public void DoSomething()
{
throw new NotImplementedException();
}
}
[ShouldBeSingleton]
public class MyComponentAsSingleton : MyComponent
{
}
class Program
{
static void Main(string[] args)
{
//option 1
IWindsorContainer container = new WindsorContainer();
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton())
.Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0));
IWindsorContainer container2 = new WindsorContainer();
container2.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.ConfigureIf(
//condition to check - do we have our custom Attribute?
registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())),
//if true register as singleton
component => component.LifestyleSingleton(),
//else register as per web request
component => component.LifestylePerWebRequest()
));
Console.ReadLine();
}
}
}
Is it an option for you register manually the exceptions first? If so, components manually registered will not be re-registered by "AllTypes"(I suggest you to use Classes instead).
If you register manually a component after a "group" registration, an exception will be thrown, but not vice versa.
For example
//YourImplementation lives in assembly 'a'
IoC.Container.Register(
Component.For<YourInterface>().ImplementedBy<YourImplementation>().LifestyleSingleton()
);
IoC.Container.Register(
Classes.FromAssemblyNamed(a)
.Pick()
.WithService.FirstInterface()
.Configure(o => o.LifeStyle.PerWebRequest)
);

Avoiding the service locator with inversion of control while dynamically creating objects

I have a WPF application based on MVVM with Caliburn.Micro and Ninject. I have a root viewmodel called ShellViewModel. It has a couple of dependencies (injected via constructor) which are configured in Caliburn's Bootstrapper. So far so good.
Somewhere down the line, there is a MenuViewModel with a couple of buttons, that in turn open other viewmodels with their own dependencies. These viewmodels are not created during creation of the root object, but I still want to inject dependencies into them from my IoC container.
I've read this question on service locator vs dependency injection and I understand the points being made.
I'm under the impression however that my MenuViewModel needs to be able to access my IoC container in order the properly inject the viewmodels that are being made dynamically..which is something I'm trying to avoid. Is there another way?
Yes, I believe you can do something a bit better.
Consider that if there was no on-demand requirement then obviously you could make those viewmodels be dependencies of MenuViewModel and so on up the chain until you get to the root of the object graph (the ShellViewModel) and the container would wire everything up.
You can put a "firewall" in the object graph by substituting something that can construct the dependencies of MenuViewModel for the dependencies themselves. The container is the obvious choice for this job, and IMHO from a practical standpoint this is a good enough solution even if it's not as pure.
But you can also substitute a special-purpose factory instead of the container; this factory would take a dependency on the container and provide read-only properties for the real dependencies of MenuViewModel. Accessing the properties would result in having the container resolve the objects and returning them (accessor methods would also work instead of properties; what's more appropriate is another discussion entirely, so just use whatever you think is better).
It may look like that you haven't really changed the status quo, but the situation is not the same it would be if MenuViewModel took a direct dependency on the container. In that case you would have no idea what the real dependencies of MenuViewModel are by looking at its public interface, while now you would see that there's a dependency on something like
interface IMenuViewModelDependencyFactory
{
public RealDependencyA { get; }
public RealDependencyB { get; }
}
which is much more informative. And if you look at the public interface of the concrete MenuViewModelDependencyFactory things are also much better:
class MenuViewModelDependencyFactory : IMenuViewModelDependencyFactory
{
private Container container;
public MenuViewModelDependencyFactory(Container container) { ... }
public RealDependencyA { get { ... } }
public RealDependencyB { get { ... } }
}
There should be no confusion over what MenuViewModelDependencyFactory intends to do with the container here because it's so very highly specialized.

MVC2 Using Unity IoC - How are controllers resolved?

I have a question concerning how the Unity container I have set up is resolving controller dependencies. I've been searching around for an explanation of this but haven't found anything that is real clear on the subject. And maybe the answer is staring me in the face... Take a look at the following code that I'm sure many MVC guys have seen:
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
IController controller;
try
{
controller = container.Resolve(controllerType) as IController;
}
catch (Exception ex)
{
throw new InvalidOperationException(string.Format("Error resolving controller {0}", controllerType.Name), ex);
}
return controller;
}
So that is my override of GetControllerInstance in my controller factory that I have set up. Obviously, the controller types are being resolved out of the Unity container but how are they getting registered in the container in the first place? How does the MVC framework know to register types in the container? I realize that the types are being resolved out of that container but I don't like not knowing how it is resolving the controller types.
It is the DefaultControllerFactory which is responsible for this. Here's how it works:
ASP.NET MVC uses reflection to list all types that inherit from Controller in all assemblies and caches them. If you really want to dig further look at the source code or use reflector and checkout this method on the DefaultControllerFactory type:
protected internal virtual Type GetControllerType(
RequestContext requestContext, string controllerName)
When a request comes it uses the routing table to determine which is the current controller and tries to find it in the list of cached controller types. If it finds one it calls the GetControllerInstance method passing the given type so that the DI framework could provide the controller instance given its type.
MVC does not register the types with Unity.
The Unity container inspects what you ask for to see if it can instantiated it with what it knows about.