I've used Autofac for years and never seen this behavior: after building, the app runs fine. However, after the app pool is recycled (I tested this by touching the web.config), I get a DependencyResolutionException:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Namespace.Controllers.HomeController' can be invoked with the available services and parameters
HomeController has one dependency, which has other dependencies, etc. But I know it can resolve them, because it does before it's recycled. Why on earth would this happen???
I autowire everything like so:
public static IContainer GetAutoFacContainer()
{
var builder = new ContainerBuilder();
var assembliesToRegister = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.FullName.StartsWith("Prefix")).ToArray();
builder.RegisterAssemblyTypes(assembliesToRegister)
.AsImplementedInterfaces().AsSelf().PropertiesAutowired().InstancePerLifetimeScope();
return builder.Build();
}
Then I use the container for WebAPI and MVC Controllers.
var autoFacContainer = DependencyRegistrar.GetAutoFacContainer();
DependencyResolver.SetResolver(new AutofacDependencyResolver(autoFacContainer));
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(autoFacContainer);
Thanks to Steven's comment above, I did find the answer on the other question as well as the Autofac site. Why these never turned up in my research I don't know.
http://docs.autofac.org/en/latest/faq/iis-restart.html
The Solution
Change AppDomain.CurrentDomain.GetAssemblies()
To BuildManager.GetReferencedAssemblies().Cast<Assembly>()
Done!
Related
I'm migrating from Unity to StructureMap. I've made some use of Unity's InterceptionBehavior.
I thought I could switch that to use StructureMap .InterceptWith and the DynamicProxyInterceptor but my interceptors have dependencies and I can't work out how to compose the interceptors using StructureMap.
var container = new Container(x =>
{
x.For<IMathService>().Use<MathService>()
.InterceptWith(new DynamicProxyInterceptor<IMathService>(new IInterceptionBehavior[]
{
// I WANT TO COMPOSE THESE INTERCEPTORS
new NegatingInterceptor(),
new CachingInterceptor()
}));
});
At the moment the only thing I can think that might be a solution is to expose my IContainer from the static IoC class and resolve my dependencies manually in my interceptor.
Eventually I'll probably get around to replacing my dynamic proxies with decorators but I'm not quite at that stage yet. I just want to get it up and running again as soon as possible so I can prove the other changes are all successful before I start to make additional changes.
Okay, I'm an idiot, you just pass an array of types instead of instances to the DynamicProxyInterceptor constructor
var container = new Container(x =>
{
x.For<IMathService>().Use<MathService>()
.InterceptWith(new DynamicProxyInterceptor<IMathService>(
new Type[]
{
// I WANT TO COMPOSE THESE INTERCEPTORS
typeof(NegatingInterceptor),
typeof(CachingInterceptor)
}));
});
This is a big mystery for me. From time to time (can't find a pattern yet) autofac fail when tries to resolve dependencies, here's error message:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'IsThereAnyNews.Mvc.Controllers.HomeController' can be invoked with the available services and parameters:
Cannot resolve parameter 'IsThereAnyNews.DataAccess.IRssChannelsRepository rssRepository' of constructor 'Void .ctor(IsThereAnyNews.Services.IUserAuthentication, IsThereAnyNews.Services.ILoginService, IsThereAnyNews.Services.ISessionProvider, IsThereAnyNews.DataAccess.IRssChannelsRepository)'.
Here's how I wire the autofac
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetCallingAssembly());
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
// other registrations goes here
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
Project setup is done like this:
ASP.MVC
-> Interfaces (where needed)
-> Autofac
-> Interface
-> Implementations (*Repository, *Services)
Yet for some mystical (for me) reason my face is being slapped with this error. Can anyone explain it to me, what am I doing wrong
EDIT
Here's implementation of RssChannelsRepository
public class RssChannelsRepository : IRssChannelsRepository
{
private readonly ItanDatabaseContext database;
public RssChannelsRepository(ItanDatabaseContext database)
{
this.database = database;
}
}
Where ItanDatabaseContext is registered like this:
builder.RegisterType<ItanDatabaseContext>().InstancePerLifetimeScope();
Can't tell if stuff are loaded, currently Im facing that issue on azure. For me that happens when I do some debug session, change piece of code here-and-there and do incremental build. Then this issue appears, but not always. To solve it I simple run full rebuild and that's it.
The problem might be caused by the AppDomain.CurrentDomain.GetAssemblies() call. According to MSDN the method:
Gets the assemblies that have been loaded into the execution context of this application domain.
If an assembly isn't loaded yet, it won't be returned from the list. Since your bootstrap code runs very early during application startup, it is possible that no method has been JITted that statically depends on a type in the assembly that contains your repository. If this is the case, that assembly won't be loaded yet and won't be returned from the GetAssemblies() method causing the registration to be absent from Autofac.
To make sure that all assemblies are loaded in a deterministic way, you should call BuildManager.GetReferencedAssemblies(). For instance:
public static void RegisterDependencies()
{
BuildManager.GetReferencedAssemblies();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
It's even more efficient to use the assemblies returned from GetReferencedAssemblies as input for Autofac, since AppDomain.GetAssemblies() would return all System.* assemblies as well, which will cause Autofac to go through them as well. For instance:
public static void RegisterDependencies()
{
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
This all is described in more detail in the Autofac documentation.
I'm attempting to implement Dependency Injection into my architecture (MVC, DDD - Domain Model, Repository). And my architecture includes ASP.NET Identity 2.0.
At this stage, I don't want DI controlling any of the Identity 2.0 objects (UserAdminController, RolesAdminController...). I'd prefer the security objects outside of DI. At this stage, integrating the Identity objects in DI looks very difficult. I had a good look to see if someone has already done this, so I could read and learn how to do this. I couldn't find anything. (Found one post which came close, but no resolution).
Anyway, I've followed the Simple Injector MVC implementation (see standard code below), and trying many things, I believe the problem lies in me calling RegisterMvcControllers.
Correct me if I'm wrong, but this statement will pickup all controllers with their name post-fixed with "controller".
Question: How can I select which controllers get registered with Simple Injector? (Is this called manually registering?)
Any help would be greatly appreciated, as I've spent most of today trying to get my head around all this, and proceed to the next step, i.e. have DI implemented, and instantiating my objects.
...
...
... called from Application_Start()
// Create a Simple Injector container
var container = new Container();
// Configure the container
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
// Verify the container's configuration
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
private static void InitializeContainer(Container container)
{
container.Register<MyService1>();
container.Register<IMyRepositoryA, MyRepositoryA>();
// Trying to include Identity into Simple Injector - please ignore
container.Register<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(new ApplicationDbContext()));
}
The RegisterMvcControllers has the following constraints on the types it registers:
The type must be public
The type must implement System.Web.Mvc.IController
The type must not be abstract
The type must not be a generic type definition
Its name must end with "Controller"
You can see what happens here in the source code.
The RegisterMvcControllers extension method calls into the SimpleInjectorMvcExtensions.GetControllerTypesToRegister method to get the list of controllers to register. You can call that method yourself to see what is registered as follows:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
So instead of calling RegisterMvcControllers you can register the controllers yourself by calling the GetControllerTypesToRegister method:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly());
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
This way you can filter out any controller you want to register manually:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
.Where(type => type.Name != "UserStore`1");
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
Another option is to override the registration:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Options.AllowOverridingRegistrations = true;
container.Register<IUserStore<ApplicationUser>>(
() => new UserStore<ApplicationUser>(new ApplicationDbContext()))
// Always set the option back to false ASAP to prevent configuration errors.
container.Options.AllowOverridingRegistrations = false;
We're trying to use MEF 2 with ASP.NET MVC 4 to support an extensible application. There are really 2 parts to this question (hope that's okay SO gods):
How do we use Microsoft.Composition and the MVC container code (MEF/MVC demo source) to replace Ninject as our DI for ICoreService, ICoreRepository, IUnitOfWork, and IDbContext?
It looks like we can't use both Ninject and the MVC container at the same time (I'm sure many are saying "duh"), so we'd like to go with MEF, if possible. I tried removing Ninject and setting [Export] attributes on each of the relevant implementations, spanning two assemblies in addition to the web project, but Save() failed to persist with no errors. I interpreted that as a singleton issue, but could not figure out how to sort it out (incl. [Shared]).
How do we load multiple assemblies dynamically at runtime?
I understand how to use CompositionContainer.AddAssemblies() to load specific DLLs, but for our application to be properly extensible, we require something more akin to how I (vaguely) understand catalogs in "full" MEF, which have been stripped out from the Microsoft.Composition package (I think?); to allow us to load all IPluggable (or whatever) assemblies, which will include their own UI, service, and repository layers and tie in to the Core service/repo too.
EDIT 1
A little more reading solved the first problem which was, indeed, a singleton issue. Attaching [Shared(Boundaries.HttpRequest)] to the CoreDbContext solved the persistence problem. When I tried simply [Shared], it expanded the 'singletonization' to the Application level (cross-request) and threw an exception saying that the edited object was already in the EF cache.
EDIT 2
I used the iterative assembly loading "meat" from Nick Blumhardt's answer below to update my Global.asax.cs code. The standard MEF 2 container from his code did not work in mine, probably because I'm using the MEF 2(?) MVC container. Summary: the code listed below now works as desired.
CoreDbContext.cs (Data.csproj)
[Export(typeof(IDbContext))]
[Shared(Boundaries.HttpRequest)]
public class CoreDbContext : IDbContext { ... }
CoreRepository.cs (Data.csproj)
[Export(typeof(IUnitOfWork))]
[Export(typeof(ICoreRepository))]
public class CoreRepository : ICoreRepository, IUnitOfWork
{
[ImportingConstructor]
public CoreRepository(IInsightDbContext context)
{
_context = context;
}
...
}
CoreService.cs (Services.csproj)
[Export(typeof(ICoreService))]
public class CoreService : ICoreService
{
[ImportingConstructor]
public CoreService(ICoreRepository repository, IUnitOfWork unitOfWork)
{
_repository = repository;
_unitOfWork = unitOfWork;
}
...
}
UserController.cs (Web.csproj)
public class UsersController : Controller
{
[ImportingConstructor]
public UsersController(ICoreService service)
{
_service = service;
}
...
}
Global.asax.cs (Web.csproj)
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
CompositionProvider.AddAssemblies(
typeof(ICoreRepository).Assembly,
typeof(ICoreService).Assembly,
);
// EDIT 2 --
// updated code to answer my 2nd question based on Nick Blumhardt's answer
foreach (var file in System.IO.Directory.GetFiles(Server.MapPath("Plugins"), "*.dll"))
{
try
{
var name = System.Reflection.AssemblyName.GetAssemblyName(file);
var assembly = System.Reflection.Assembly.Load(name);
CompositionProvider.AddAssembly(assembly);
}
catch
{
// You'll need to craft exception handling to
// your specific scenario.
}
}
}
}
If I understand you correctly, you're looking for code that will load all assemblies from a directory and load them into the container; here's a skeleton for doing that:
var config = new ContainerConfiguration();
foreach (var file in Directory.GetFiles(#".\Plugins", "*.dll"))
{
try
{
var name = AssemblyName.GetAssemblyName(file);
var assembly = Assembly.Load(name);
config.WithAssembly(assembly);
}
catch
{
// You'll need to craft exception handling to
// your specific scenario.
}
}
var container = config.CreateContainer();
// ...
Hammett discusses this scenario and shows a more complete version in F# here: http://hammett.castleproject.org/index.php/2011/12/a-decent-directorycatalog-implementation/
Note, this won't detect assemblies added to the directory after the application launches - Microsoft.Composition isn't intended for that kind of use, so if the set of plug-ins changes your best bet is to detect that with a directory watcher and prompt the user to restart the app. HTH!
MEF is not intended to be used as DI framework. Which means that you should separate your "plugins" (whatever they are) composition from your infrastructure dependencies, and implement the former via MEF and the latter via whatever DI framework you prefer.
I think there are a little misunderstandings on what MEF can and can't do.
Originally MEF was conceived as purely an extensibility architecture, but as the framework evolved up to its first release, it can be fully supported as a DI container also. MEF will handle dependency injection for you, and does so through it's ExportProvider architecture. It is also entirely possible to use other DI frameworks with MEF. So in reality there are a number of ways things could be achieved:
Build a NinjectExportProvider that you can plug into MEF, so when MEF is searching for available exports, it will be able to interrogate your Ninject container.
Use an implementation of the Common Services Locator pattern to bridge between MEF and Ninject or vice versa.
Because you are using MEF for the extensibility, you'll probably want to use the former, as this exposes your Ninject components to MEF, which in turn exposes them to your plugins.
The other thing to consider, which is a bit disappointing, is in reality there isn't a lot of room for automagically plugging in of features ala Wordpress on ASP.NET. ASP.NET is a compiled and managed environment, and because of that you either resort to late-binding by loading assemblies manually at runtime, or you restart the application to pick up the new plugins, which sort of defeats the object of being able to plug new extensions in through the application.
My advice, is plan your architecture to pick up any extensibility points as startup and assume that any core changes will require a deployment and application restart.
In terms of the direct questions asked:
The CompositionProvider accepts in instance of ContainerConfiguration which is used internally to create the CompositionContainer used by the provider. So you could use this as the point by which you customise how you want your container to be instantiated. The ContainerConfiguration supports a WithProvider method:
var configuration = new ContainerConfiguration().WithProvider(new NinjectExportDescriptorProvider(kernel));
CompositionProvider.SetConfiguration(configuration);
Where NinjectExportDescriptorProvider might be:
public class NinjectExportDescriptorProvider: ExportDescriptorProvider
{
private readonly IKernel _kernel;
public NinjectExportDescriptorProvider(IKernel kernel)
{
if (kernel == null) throw new ArgumentNullException("kernel");
_kernel = kernel;
}
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(
CompositionContract contract, DependencyAccessor dependencyAccessor)
{
var type = contract.ContractType;
if (!_kernel.GetBindings(type).Any())
return NoExportDescriptors;
return new[] {
new ExportDescriptorPromise(
contract,
"Ninject Kernel",
true, // Hmmm... need to consider this, setting it to true will create it as a shared part, false as new instance each time,
NoDependencies,
_ => ExportDescriptor.Create((c, o) => _kernel.Get(type), NoMetadata)) };
}
}
}
Note: I have not tested this, this is all theory, and is based on the example AppSettingsExportDescriptorProvider at: http://mef.codeplex.com/wikipage?title=ProgrammingModelExtensions
It's different from using the standard ExportProvider, because using the CompostionProvider is built around lightweight composition. But essentially you're wrapping up access to your Ninject kernel and making it available to your CompositionContainer.
As with adding a specific new provider (see above), you can use the ContainerConfiguration to read the available assemblies, probably something like:
var configuration = new ContainerConfiguration().WithAssemblies(AppDomain.GetAssemblies())
Again, I haven't tested all of this, but I hope it at least points you in the right direction.
I recently followed Aaron Powell's posts on supporting MVC controllers with Umbraco 4:
http://www.aaron-powell.com/umbraco/using-mvc-in-umbraco-4 and http://www.aaron-powell.com/umbraco/using-mvc-in-umbraco-4-revisited
Everything works as expected. I can set up controllers and they work seamlessly well along side umbraco's pages. The thing is I'm trying to setup IoC with Ninject and haven't been able to get it working.
I've setup a class in App_Start that uses web activator to attach to the PreApplicationStartMethod and defined my kernel configuration as I have always had in the past:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
//Standard Modules
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IConfigurationManager>().To<ConfigurationManagerWrapper>().InRequestScope();
//Security
kernel.Bind<ISecurity>().To<Security>().InSingletonScope();
kernel.Bind<IMembershipAuthorization>().To<MembershipAuthorization>();
kernel.Bind<IFormsAuthorization>().To<FormsAuthorization>();
//Registering my services, repositories, and connections
RegisterRepositories(kernel);
RegisterServices(kernel);
RegisterConnections(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
return kernel;
}
I've debugged the solution and this code gets run. But everytime I call a controller the injection isn't made and I get the "No parameterless constructor is defined" error.
Does anyone know how to get IoC working in this scenario?
We started from scratch. Using the Umbraco compiled binaries/website instead of the sources. From that point we installed MVC4 and Ninject using nuGet and everything seems to work fine.
Thanks to those who helped anyways!