I've got a ConfigurationReader class that I'm trying to wire up using StructureMap or AutoFac (I haven't settled on which container I'm using).
public class ConfigurationReader {
private string _filePath;
public ConfigurationReader(string filePath){
this._filePath = filePath;
}
public IList<Baz> ListStuff(){
//do something with _filePath;
}
}
There will be 1..n to instances of this class based on how the app is configured (web.config will contain a delimited list of files). I'm looking for an extension point in either IoC container that would allow me to leverage them to create instances of ConfigurationReader.
Well, in AutoFac you can just register each one in the Container (during Application_Start for example).
Whenever you need to read all configurations you can add a dependency to IEnumerable<ConfigurationReader> (or IConfigurationReader if you decide to extract an interface) and it will provide you with all of them.
Something like this:
var builder = new ContainerBuilder();
foreach(var file in ConfigurationManager.AppSettings[yourKey].Split(','))
{
var fileName = file;
builder.Register(c => new ConfigurationReader(fileName));
}
DependencyResolver.SetResolver(new AutofacDependencyResolver(builder.Build()));
If you extract interfaces, then you may want to register by adding the .AsImplementedInterfaces() or .As<IConfigurationReader>() at end as well.
Related
Within ConfigureServices I'm setting up a number of services (this works). In the same method I'm trying to configure a custom file provider (for Razor). It looks like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.FileProvider = new CustomFileProvider(???);
});
CustomFileProvider has a few dependencies (that are all configured), but how can I ask the DI to give me an instance of CustomFileProvider right after all the services have been configured?
From what I can see the DI only injects in constructors, but in my case I need a "please give me an instance of CustomFileProvider right here" option.
If you want to be able to resolve services from the container while configuring some options, you need to leverage the IConfigureOptions<TOption> infrastructure, which most of MVC uses to set up the option defaults. See RazorViewEngineOptionsSetup for an example.
First, add the services you need to the collection:
services.AddSingleton<IDependency1, Dependency1>();
services.AddSingleton<IDependency2, Dependency2>();
Then, implement the setup class:
public class CustomFileProviderRazorViewEngineOptionsSetup : ConfigureOptions<RazorViewEngineOptions>
{
public CustomFileProviderRazorViewEngineOptionsSetup(IServiceProvider serviceProvider)
: base(options => ConfigureRazor(options, serviceProvider))
{
}
private static void ConfigureRazor(RazorViewEngineOptions options, IServiceProvider serviceProvider)
{
// Alternative 1 - Resolve each service and new up the instance.
var dependency1 = serviceProvider.GetService<IDependency1>();
var dependency2 = serviceProvider.GetService<IDependency2>();
options.FileProviders.Add(new CustomFileProvider(dependency1, dependency2));
// Alternative 2 - Same as alternative 1, but with moar magic ;)
options.FileProviders.Add(ActivatorUtilities.CreateInstance<CustomFileProvider>(serviceProvider));
// Alternative 3 - Just resolve CustomFileProvider from the service provider.
// This requires it to be registered first, of course.
options.FileProviders.Add(serviceProvider.GetService<CustomFileProvider>());
}
}
This is resolved from the container, so it'll allow you to inject an IServiceProvider, which can again be used to resolve the services you need. You could optionally add the CustomFileProvider to the container and resolve that directly instead, like in alternative 3.
Finally, add the setup class to the service collection:
services.TryAddEnumerable(
ServiceDescriptor.Transient<
IConfigureOptions<RazorViewEngineOptions>,
CustomFileProviderRazorViewEngineOptionsSetup>());
This will add the setup to the options builder pipeline, which means it'll run with the other registered instances of IConfigureOptions<RazorViewEngineOptions> to setup the options object.
I have a console app and web API both referencing the same data layer which is a separate project.
In that data layer, I have a class that requires a repository that we are grabbing from the container when that class is instantiated.
In that class, it has a base class which we are doing the following in the constructor to setup the Repository:
IContainerAccessor containerAccessor = HttpContext.Current.ApplicationInstance as IContainerAccessor;
Repository = containerAccessor.Container.Resolve<IRepository>();
What would be the best way to set this up? This is obviously a problem for our console application as it has no HttpContext.
If I'm correct you want to setup your console app so it can inject classes from the shared data layer.
To do so, you need to create an installer for the console app and tell it to run the installers in the shared library, but to modify the life style from 'PerWebRequest' to 'Singleton' or 'Transient'.
For more information read this article:
http://blog.ploeh.dk/2010/04/26/ChangingWindsorlifestylesafterthefact/
Be aware that changing this may cause problems.
I.e.: If multiple components configured as "perWebRequest" require a 'Unit-Of-Work' to be injected, then this uow will be different for all components if you change the life style to transient.
Changing it to Singleton causes the same but opposite problem. Objects that are created now will have the same object for different requests ...
If you are okay with the problems this code should get you starting
public class ConsoleAppInstaller: IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// 1) make sure we do not use PerWebRequest life style types
var convertWebToTransient = new WebToTransientConvertor();
container.Kernel.ComponentModelBuilder.AddContributor(convertWebToTransient);
// 2) call installers on all libraries we use ...
container.Install(FromAssembly.Containing<SharedDataLayerInstaller>());
// 3) link internal services ...
container.Register(Component.For<IXxxxFactory>().AsFactory());
container.Register(Component.For<IYyyyFactory>().AsFactory());
container.Register(Classes.FromThisAssembly().Where(c => typeof(Form).IsAssignableFrom(c)).LifestyleTransient());
}
public static IWindsorContainer Bootstrap()
{
return new WindsorContainer().Install(FromAssembly.This());
}
}
/// <summary>
/// This class allows to intercept installers using PerWebRequest lifestyles and replaces them with Transient life styles.
/// <code>container.Kernel.ComponentModelBuilder.AddContributor(new WebToTransientConvertor())</code>
/// </summary>
public class WebToTransientConvertor : IContributeComponentModelConstruction
{
//http://blog.ploeh.dk/2010/04/26/ChangingWindsorlifestylesafterthefact/
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (model.LifestyleType == LifestyleType.PerWebRequest)
//model.LifestyleType = LifestyleType.Transient;
model.LifestyleType = LifestyleType.Singleton;
}
}
I am trying to find out how I can pass the StructrueMap container to a class that I wrote that inherits from another (MS-Class).
namespace TheNamespace
{
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
/* **This can't be done**
public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager)
{
_someField= portalTenantManager;
}*/
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
//How does it work ???????????
var portalTenantManager = container.GetInstance<IPortalTenantManager>();
//Do something with the portalTenantManager
}
}
I need portalTenantManager to be the Instance that I have defined in my container in the Global.asax.
My Global Assax has these things setup:
protected void Application_Start()
{
var container = new Container();
container.Configure(x =>
{ ....
....
x.For<IPortalTenantManager>().Use<PortalTenantManager>();
});
...
...
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container));
...
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapApiControllerFactory(container);
...
}
Edit:
Because of the comments of #NightOwl888 I'll explain a bit further what this class does. (Hopefully explaining so why my hands are tied)
My application is able to authenticate a user with Azure Active Directory and is Multi-tenant capable. In the authentication pipeline I have the possibility to store the validation endpoints in my database instead of the default way on the web.config file. See MSDN
and this, which actually is explaining exactly what I'm doing.
So I registered my class in the web.config under the Tag issuerNameRegistry. At some point of the validation pipeline my class is instantiated and the overriden method IsThumbprintValid is beeing called. The problem is that the class registered in issuerNameRegistry expects a parameterless constructor (there it is! the constrained construction!), therefore I cannot create a constructor that would solve my problem.
Thanks for your help
It turns out that this question has been asked before on MSDN, the answer of which was provided by Travis Spencer in 2 different posts.
it is typical in my experience to have a single container and use that service- or Web-side-wide. In the startup of the service or Web app, you can create the container, register the dependencies, new up an instance of your SecurityTokenServiceConfiguration class, resolve your dependencies, use it to punch out a SecurityTokenService object, and host it.
After the first beta, we really pushed for DI support. We got a little hook in beta 2. You can now create a custom SecurityTokenServiceConfiguration class that overrides the virtual CreateSecurityTokenService method. The implementation in Microsoft's SecurityTokenServiceConfiguration does Activator.CreateInstance; yours can do IoC. This can include the resolution of an IssuerNameRegistiry. Something like this perhaps:
RequestSecurityTokenResponse Issue(IClaimsPrincipal principal, RequestSecurityToken request)
{
SecurityTokenServiceConfiguration config = new MyGoodSecurityTokenServiceConfiguration();
SecurityTokenService sts = config.CreateSecurityTokenService();
RequestSecurityTokenResponse rstr = sts.Issue(principal, request);
return rstr;
}
public class MyGoodSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
{
public override SecurityTokenService CreateSecurityTokenService()
{
IssuerNameRegistry = IoC.Resolve<IssuerNameRegistry>();
var sts = IoC.Reslove<SecurityTokenService>();
return sts;
}
}
Of course, this means that you need to create a static instance of your DI container so it is accessible to your SecurityTokenServiceConfiguration class. Personally, I don't like that idea because it makes your DI container accessible throughout the application, which can lead to abuse of the DI container as a service locator.
Ideally, there would be a way in any DI friendly framework to pass the container into an abstract factory in order to resolve service dependencies. However, since I am not familiar with WIF it is unclear whether that can be done - perhaps the class where the Issue method exists could have a constructor added? The trick is to keep walking up the chain until you find the first place in the framework where you can intervene and do all of your DI configuration there.
When you create a controller in MVC, you don't have to do any additional registration for it. Same goes with adding areas. As long as your global.asax has an AreaRegistration.RegisterAllAreas() call, no additional setup is necessary.
With AutoMapper, we have to register the mappings using some kind of CreateMap<TSource, TDestination> call. One can do these explicitly with the static Mapper.CreateMap, or by deriving from the AutoMapper.Profile class,overriding the Configure method, and calling CreateMap from there.
It seems to me like one should be able to scan an assembly for classes that extend from Profile like MVC scans for classes that extend from Controller. With this kind of mechanism, shouldn't it be possible to create mappings simply by creating a class that derives from Profile? Does any such library tool exist, or is there something built into automapper?
I don't know if such tool exists, but writing one should be pretty trivial:
public static class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(x => GetConfiguration(Mapper.Configuration));
}
private static void GetConfiguration(IConfiguration configuration)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var profiles = assembly.GetTypes().Where(x => x != typeof(Profile) && typeof(Profile).IsAssignableFrom(x));
foreach (var profile in profiles)
{
configuration.AddProfile((Profile)Activator.CreateInstance(profile));
}
}
}
}
and then in your Application_Start you could autowire:
AutoMapperConfiguration.Configure();
As a slight improvement to the answer from #Darin Dimitrov, in AutoMapper 5 you can give it a list of Assemblies to scan like this:
//--As of 2016-09-22, AutoMapper blows up if you give it dynamic assemblies
var assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => !x.IsDynamic);
//--AutoMapper will find all of the classes that extend Profile and will add them automatically
Mapper.Initialize(cfg => cfg.AddProfiles(assemblies));
Let's say we have class:
public class WithDependencies
{
public WithDependencies(IAmDependencyOne first, IAmDependencyTwo second)
// ...
}
Now the question. How do you create objects of WithDependencies class in an application?
I know there are many ways.
new WithDependencies(new DependencyOne(), new DependencyTwo());
new WithDependencies(IoC.Resolve(IDependencyOne), IoC.Resolve(IDependencyTwo());
// register IDependencyOne, IDependencyTwo implementations at app start
IoC.Resolve(WithDependencies);
// register IDependencyOne, IDependencyTwo implementations at app start
// isolate ourselves from concrete IoC Container
MyCustomWithDependenciesFactory.Create();
and so on...
What do you think is the way to do it?
Edit:
Because I don't get answers or I don't understand them I'll try to ask again. Let's say that on some event (button, timer, whatever) I need new object WithDependencies(). How do I create it? Assume IoC container is already configured.
It depends on the context, so it's impossible to provide a single answer. Conceptually you'd be doing something like this from the Composition Root:
var wd = new WithDependencies(new DependencyOne(), new DependencyTwo());
However, even in the absence of a DI Container, the above code isn't always unambiguously the correct answer. In some cases, you might want to share the same dependency among several consumers, like this:
var dep1 = new DependencyOne();
var wd = new WithDependencies(dep1, new DependencyTwo());
var another = AnotherWithDependencies(dep1, new DependencyThree());
In other cases, you might not want to share dependencies, in which case the first option is more correct.
This is just a small glimpse of an entire dimension of DI concerned with Lifetime Management. Many DI Containers can take care of that for you, which is one excellent argument to prefer a DI Container over Poor Man's DI.
Once you start using a DI Container, you should follow the Register Resolve Release pattern when resolving types, letting Auto-wiring take care of the actual composition:
var wd = container.Resolve<WithDependencies>();
The above example assumes that the container is already correctly configured.
If you need to create a dependency which has its own dependencies, you can either A) do it yourself, or B) ask something else to do it for you. Option A negates the benefits of dependency injection (decoupling, etc.), so I would say option B is a better starting point. Now, we have chosen to use the factory pattern, no matter whether it takes the form of a service locator (i.e. IoC.Resolve), a static factory, or an instance factory. The point is that we have delegated that responsibility to an external authority.
There are a number of trade-offs required for static accessors. (I went over them in another answer, so I won't repeat them here.) In order to avoid introducing a dependency on the infrastructure or the container, a solid option is to accept a factory for creating WithDependencies when we need an instance somewhere else:
public class NeedsWithDependencies
{
private readonly IWithDependenciesFactory _withDependenciesFactory;
public NeedsWithDependencies(IWithDependenciesFactory withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory.Create();
...Use the instance...
}
}
Next, we can create a container-specific implementation of the factory:
public class WithDependenciesFactory : IWithDependenciesFactory
{
private readonly IContainer _container;
public WithDependenciesFactory(IContainer container)
{
_container = container
}
public WithDependencies Create()
{
return _container.Resolve<WithDependencies>();
}
}
Now NeedsWithDependencies is completely isolated from any knowledge of how WithDependencies gets created; it also exposes all its dependencies in its constructor, instead of hiding dependencies on static accessors, making it easy to reuse and test.
Defining all those factories can get a little cumbersome, though. I like Autofac's factory relationship type, which will detect parameters of the form Func<TDependency> and automatically inject a function which serves the same purpose as the hand-coded factory above:
public class NeedsWithDependencies
{
private readonly Func<WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo()
{
var withDependencies = _withDependenciesFactory();
...Use the instance...
}
}
It also works great with runtime parameters:
public class NeedsWithDependencies
{
private readonly Func<int, WithDependencies> _withDependenciesFactory;
public NeedsWithDependencies(Func<int, WithDependencies> withDependenciesFactory)
{
_withDependenciesFactory = withDependenciesFactory;
}
public void Foo(int x)
{
var withDependencies = _withDependenciesFactory(x);
...Use the instance...
}
}
Sometimes I try to get rid of factories or at least not depend directly on them, so Dependency Injection (without factories) is useful of course.
Therefore I use Google Juice, cause its a small little framework using Java Annotations and you can quickly change your injections / dependencies. Just take a look at it:
http://code.google.com/p/google-guice/