I have a DevExpress example mvc web site application. It use Castle Windsor as an IOC. I just tried to replace via Autofac but no luck!
here is the sample code:
container
.Register(Component
.For<DbRepositories.ClinicalStudyContext>()
.LifestylePerWebRequest()
.DependsOn(new { connectionString }))
.Register(Component
.For<DbRepositories.IClinicalStudyContextFactory>()
.AsFactory())
.Register(Component
.For<FirstStartInitializer>()
.LifestyleTransient())
.Register(Component
.For<IUserRepository>()
.ImplementedBy<DbRepositories.UserRepository>())
and this is my Autofac conversion:
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.Register(c =>
new DbRepositories.AdminContext(connectionString))
.InstancePerHttpRequest();
builder.RegisterType<DbRepositories.IAdminContextFactory>()
.As<DbRepositories.IAdminContextFactory>();
builder.RegisterType<DbRepositories.UserRepository>()
.As<IUserRepository>().InstancePerHttpRequest();
there is no implementetion for AsFactory() on Autofac regarding my research.
this is the IAdminContextFactory interface:
public interface IAdminContextFactory
{
AdminContext Retrieve();
}
and this is the error application says:
No constructors on type
'Admin.Infrastructure.EFRepository.IAdminContextFactory' can be found
with 'Public binding flags'.
can anyone help?
thanks.
Your IAdminContextFactory registration will fail, because the first part of the RegisterType must be a service type. In this case, a class that implements the IAdminContextFactory interface. Autofac tries to build an instance of the type, which certainly will fail because you cannot instantiate an interface.
So, what you need is an implementation of the IAdminContextFactory interface. The Castle AsFactory method generates this implementation for you. You can get this behavior with the Autofac AggregateService extra.
With the bits in place you can do:
builder.RegisterAggregateService<IAdminContextFactory>();
Related
I was going through this article about dependency injection http://www.asp.net/web-api/overview/advanced/dependency-injection
It shows Unity Container from Microsoft.
There are a few things that are not making sense to me
for example, following line
public ProductsController(IProductRepository repository)
The above is the constructor of Controller. I need to know who passes the repository to the constructor? ANd is that made possible by registering IProductRepository interface with Unity?
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Other Web API configuration not shown.
}
Is the above code is all needed to make MVC pass the object to the constructor of a controller?
You answered your own question:
is that made possible by registering IProductRepository interface with Unity?
Yes.
When you request to resolve a type using Unity, the container searches for public constructors. If the constructor needs some implementation (IProductRepository in your case), the container searches within its registrations for an implementation for all the needed parameters. If found, it resolves that. This is a recursive process.
So yes. You need to register an implementation of IProductRepository using the container in order to resolve an instance of the Controller using that container.
One of the classes in my Umbraco project depends on IContentService. I'm trying to provide an IContentService to this class with an IOC container.
Here is how I'm registering IContentService with my IOC (Autofac)
builder.RegisterType<Umbraco.Core.Services.ContentService>().As<IContentService>();
However, Umbraco.Core.Services.ContentService requires these constructor parameters:
public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IPublishingStrategy publishingStrategy, IDataTypeService dataTypeService, IUserService userService);
Autofac gets stuck because it doesn't know about any of these types yet. Here's a stack trace:
Exception Details: Autofac.Core.DependencyResolutionException: None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Umbraco.Core.Services.ContentService' can be
invoked with the available services and parameters:Cannot resolve parameter
'Umbraco.Core.Persistence.RepositoryFactory repositoryFactory' of constructor 'Void
.ctor(Umbraco.Core.Persistence.UnitOfWork.IDatabaseUnitOfWorkProvider, Umbraco.Core.Persistence.RepositoryFactory,
Umbraco.Core.Logging.ILogger, Umbraco.Core.Events.IEventMessagesFactory, Umbraco.Core.Publishing.IPublishingStrategy,
Umbraco.Core.Services.IDataTypeService, Umbraco.Core.Services.IUserService)'.
Which types should I register with Autofac so that my ContentService can be instantiated?
Here's how I solved this particular problem. Thanks to Claus for the help.
I need to use RegisterInstance() (docs here) instead of RegisterType<T>()
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var builder = new ContainerBuilder();
// Register the components we need resolving with Autofac
builder.RegisterInstance(applicationContext.Services.MemberService).As<IMemberService>();
builder.RegisterInstance(applicationContext.Services.ContentService).As<IContentService>();
// ... Configuration for dependency resolution here ...
}
The reason for this is that Umbraco creates an instance of ContentService and configures it correctly. Autofac needs to be told to use this instance instead of trying to create it's own.
IProductRepositoryProxy ProductDataServiceProviderInstance = new ServiceProductDataProvider();
builder.RegisterInstance(ProductDataServiceProviderInstance).As<IProductRepositoryProxy>();
VS
builder.RegisterType<ServiceProductDataProvider>().As<IProductRepositoryProxy>().InstancePerRequest();
I saw this code from an ex-employee here and wonder if the guy wanted to register a .SingleInstance() behavior.
builder.RegisterType<ServiceProductDataProvider>().As<IProductRepositoryProxy>().SingleInstance();
Is the manual newing-up of the ServiceProductDataProvider with RegisterInstance not the same as the Register .SingleInstance() ??
Is the manual newing-up of the ServiceProductDataProvider with RegisterInstance not the same as the Register .SingleInstance() ??
The RegisterInstance allows you to register a single instance in AutoFac.
The difference between RegisterInstance and RegisterType + SingleInstance methods is that the RegisterInstance method allows you to register an instance not built by Autofac.
But both solution will result in registering a singleton in Autofac.
By the way, both registration are equivalent in the following code sample
var instance = GetInstanceFromSomewhere();
builder.RegisterInstance<IService>(instance);
builder.Register(c => instance).As<IService>().SingleInstance();
I want to register WCF client channels in autofac, so I can resolve them simply by including the service contract interface in the constructor, e.g. like this:
public LoginFormController(ILoginService loginService)
{ ...
I have a factory that creates the channels for me, with a single public generic method:
public T GetChannel<T>()
I register my factory:
Builder.RegisterType<ClientChannelManager>().As<IClientChannelManager>();
I can't figure out if there is a syntax to register my client channel. This works, but its not what I want:
Builder.Register(c => new ClientChannelManager(new SettingsProvider()).GetChannel<ILoginService>()).As<ILoginService>();
Instead of creating new instance of ClientChannelManager and its constructor arguments, I want it resolved from the container.
The best I have come up with is a static GetChannel method in my factory that resolves an instance from the container explicitly:
public static T ResolveChannel<T>(IComponentContext context)
{
IClientChannelManager manager = context.Resolve<IClientChannelManager>();
return manager.GetChannel<T>();
}
And register the service contract with a call to the static method:
Builder.Register(c => ClientChannelManager.ResolveChannel<ILoginService>(c)).As<ILoginService>();
Anyone know a more elegant syntax/solution for this?
There is a whole article on registering and consuming WCF services using Autofac on the Autofac wiki that shows exactly what you're asking for: http://docs.autofac.org/en/latest/integration/wcf.html
This is probably a bit trivial, but I must be doing something wrong. I have an MVC project, where I have two projects controlled by IoC using Windsor:
The MVC project
A project with services
Normally I would register the services using an XML file. However, I want to register all services and interfaces automatically.
All my services is placed in my services project called LetterAmazer.Business.Services, under the namespace LetterAmazer.Business.Services.Services. My interfaces, which the services derive from, is in the namespace LetterAmazer.Business.Services.Domain .
I have tried to set it up in my Global.asax, in the following way:
private void InitializeContainer()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
Container.Register(Component.For<IWindsorContainer>().Instance(this.Container));
Container.Install(new BootstrapInstaller());
Container.Register(
Classes.FromAssemblyInDirectory(new AssemblyFilter("LetterAmazer.Business.Services"))
.InNamespace("LetterAmazer.Business.Services.Services"));
Container.Install(new WebWindsorInstaller());
var provider = new WindsorFilterAttributeFilterProvider(this.Container);
FilterProviders.Providers.Add(provider);
DependencyResolver.SetResolver(new WindsorDependencyResolver(ServiceFactory.Container));
}
public IWindsorContainer Container
{
get { return ServiceFactory.Container; }
}
But this provides several issues. First of all, it doesn't find any services when running the Classes.FromAssemblyInDirectory call. Furthermore, this wouldn't get the interfaces.
So I am basically asking how to solve this problem in a best practice way? I have 30+ services, and I want them all, so it would make sense to add them by conventation rather than hand pick.
EDIT:
The code I ended up with:
var assembly = Assembly.LoadFrom(Server.MapPath("~/bin/LetterAmazer.Business.Services.dll")); ;
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
I haven't used Classes.FromAssemblyInDirectory() method but I usually use FromThisAssembly() or 'FromAssemblyContaining()' methods to select assemblies. Simetimes FromAssembly("AssemblyName") is used.
I would write the following code the following way if there is no base interface for all seervices:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
If there is a generic interface IService<T> I would use the following registration:
container.Register(
Classes.FromAssembly("LetterAmazer.Business.Services")
.BasedOn(typeof(IService<>))
.WithServiceAllInterfaces());
I'd like to add that all your services will be registered as Singletons if life style is not specified during registration.
You can find detailed information in the article Registering components by conventions from Castle Windsor website.