I'm adding autofac to an existing project and some of the service implementations require their Initialize method to be called and passed configuration information. Currently I'm using the code:
builder.Register(context =>
{
var service =
new SqlTaxRateProvider(context.Resolve<IUserProvider>());
service.Initialize(config);
return service;
}
).As<ITaxService>()
.SingleInstance();
which works but I'm still creating the object myself which is what I'm trying to get away from this and allow autofac to handle it for me. Is it possible to configure a post create operation that would carry out the custom initialisation?
To give you an idea of what I'm after ideally this would be the code:
builder.RegisterType<SqlTaxRateProvider>()
.As<ITaxService>()
.OnCreated(service=> service.Initialize(config))
.SingleInstance();
Update:
I am using Autofac-2.1.10.754-NET35
.OnActivating(e => e.Instance.Initialize(...))
should do the trick.
You might also investigate the Startable module (see the Startable entry in the Autofac wiki).
Mark's suggestion to do initialisation in the constructor is also a good one. In that case use
.WithParameter(new NamedParameter("config", config))
to merge the config parameter in with the other constructor dependencies.
Related
I'm having an issue with Autofac where it seems like EnableClassInterceptors is interfering with my ability to use .WithParameter(...). When the constructor is being called on Service using the code below, someString is not being populated. Notes:
I've tried using ResolvedParameter instead, it does not help (note: my Resolved parameter still includes the name of the parameter when I tried that)
If I remove EnableClassInterceptors and InterceptedBy, the parameter does get populated properly. This, however, isn't a valid solution as I need the interceptors.
Re-ordering WithParameter, EnableClassInterceptors, and InterceptedBy does not help.
Looking at Type Interceptors, specifically the "Class Interceptors and UsingConstructor" section, on docs.autofac.org, it mentions that using EnableClassInterceptors will cause ConstructUsing to fail. I think something similar might be happening with my scenario below.
Snippet of my registration code looks like this:
var builder = new ContainerBuilder();
builder.RegisterType<Dependency>.As<IDependency>.InstancePerLifetimeScope();
builder.RegisterType<Service>()
.As<IService>()
.WithParameter(new NamedParameter("someString", "TEST"))
.EnableClassInterceptors()
.InterceptedBy(typeof(LogExceptionsInterceptor));
Service's constructor looks something like this:
public class Service : IService
{
public Service(IDependency dependency, string someString)
{
if(dependency == null)
throw ArgumentNullException(nameof(dependency));
if(someString == null)
//**throws here**
throw ArgumentNullException(nameof(someString));
}
}
[Guess] What I'm thinking is happening is that when EnableClassInterceptors is called, a proxy class is generated with a constructor that works on top of the existing one, but the parameter names do not copy over into the proxy class/constructor.
Is this a problem? Is there a way to form the registration that allows both WithParameter and EnableClassInterceptors to be used together? Is it a bug in Autofac?
Your guess is correct: the generated proxy class does not keep the constructor parameter names.
Currently there is no way to influence this in DynamicProxy so this is not a bug of Autofac (although this edge case currently not documented on the Autofac documentation website).
This is how your original Service class's parameters look like:
typeof(Service).GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[2]}
[0]: {ConsoleApplication10.IDependency dependency}
[1]: {System.String someString}
But the generated proxy does not keep the names:
GetType().GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[3]}
[0]: {Castle.DynamicProxy.IInterceptor[] }
[1]: {ConsoleApplication10.IDependency }
[2]: {System.String }
So you have two not very robust options to workaround this limitation with WithParameter:
use the TypedParamter with string as the type:
.WithParameter(new TypedParameter(typeof(string), "TEST"))
However if you have multiple paramters with the same type this won't work
use the PositionalParameter in this case you need to add 1 if the type is proxied
.WithParameter(new PositionalParameter(2, "TEST"))
Another options would be to don't use a primitive string type but create a wrapper e.g. MyServiceParameter or create another service which can provide these string configuration values to your other services.
I have the following class, which uses constructor injection:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
For most methods in this class, I simply create Moq mocks for IRepository and IProvider and construct the Service. However, there is one method in the class that calls several other methods in the same class. For testing this method, instead of testing all those methods together, I want to test that the method calls those methods correctly and processes their return values correctly.
The best way to do this is to mock Service. I've mocked concrete classes with Moq before without issue. I've even mocked concrete classes that require constructor arguments with Moq without issue. However, this is the first time I've needed to pass mocked arguments into the constructor for a mocked object. Naturally, I tried to do it this way:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
However, that does not work. Instead, I get the following error:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
This works fine if Service's constructor takes simple arguments like ints and strings, but not if it takes interfaces that I'm mocking. How do you do this?
Why are you mocking the service you are testing? If you are wishing to test the implementation of the Service class (whether that be calls to mocked objects or not), all you need are mocks for the two interfaces, not the test class.
Instead of:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Shouldn't it be this instead?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
I realize that it is possible to mock concrete objects in some frameworks, but what is your intended purpose? The idea behind mocking something is to remove the actual implementation so that it does not influence your test. But in your question, you have stated that you wish to know that certain classes are called on properly, and then you wish to validate the results of those actions. That is undoubtedly testing the implementation, and for that reason, I am having a hard time seeing the goals of mocking the concrete object.
I had a very similar problem when my equivalent of Service had an internal constructor, so it was not visible to Moq.
I added
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
to my AssemblyInfo.cs file for the implementing project. Not sure if it is relevant, but I wanted to add a suggestion on the off chance that it helps you or someone else.
It must be old version issue, all is ok with latest version. Nick, Please check!
P.s.: I started bounty by misstake (I had wrong signature in my constructor).
I'm working on legacy code.
I have different methods of the same class that pass different arguments to the constructor of a dependency. I'm trying to get some basic IoC usage introduced. Right now I have StructureMap passing my arguments like this:
var thing = ObjectFactory.GetInstance<IThingInterface>(new ExplicitArguments(
new Dictionary<string, object> {
{ "constructorArgA", notShown },
{ "constructorArgB", redacted.Property } }));
Where the actual properties passed for constructorArgA and B change depending on where I am.
Instead of "constructorArgA" is there a way to configure this via actual types, like you can do when configuring the objectFactory, like:
x.For<IHidden>().Use<RealType>()
.Ctor<IConfig>().Is(new Func<IContext, IConfig>(
(context) => someMethodToGetIConfig()));
If I were writing this from scratch I'd probably structure the dependencies a bit different to avoid this, but that's not an option for me right now.
This is something of a classic/common question with DI Containers.
My first choice would be to create a "manual" abstract factory to create IThingInterface, and then use Structuremap to inject IThingInterfaceFactory where it is needed. By manual factory, I mean a class the calls new ThingInterface() and returns it. If you do it this way, your implementation will no longer be container-managed, and if it has dependencies, they would no longer be provided by the container (may or may not be a problem for you).
Second choice would be to create an abstract factory that actually uses/wraps the container. So basically your first code snippet but wrapped in a factory class where the Create() method takes your parameters. This has the advantage of everything (including your implementation and its dependencies) being container-managed, but the disadvantage of referencing your container directly (which is not a best practice--see Article on Composition Roots).
You could also do setter injection, but I would personally consider it a last resort.
Castle Windsor has a good solution to this problem built in (Typed Factory Facility). Not sure if switching containers in an option, but you might consider it.
I am investigating the use of Autofac in our web application having previously used Castle Windsor in the past.
The thing that I really like with Autofac is being able to express dynamic component construction through lamda expressions, as opposed to creating DependancyResolvers etc. in Windsor.
One scenario I have is that I want a particular component to be registered at ASP.NET session level scope. With Windsor I would create/source a new LifestyleManager, however with Autofac I came up with this:
//Register SessionContext at HTTP Session Level
builder.Register(c =>
{
HttpContext current = HttpContext.Current;
//HttpContext handes delivering the correct session
Pelagon.Violet.Core.Interfaces.SessionContext instance = current.Session["SessionContext"] as Pelagon.Violet.Core.Interfaces.SessionContext;
if (instance == null)
{
instance = c.Resolve<Pelagon.Violet.Core.Interfaces.SessionContext>();
current.Session["SessionContext"] = instance;
}
return instance;
})
.FactoryScoped();
Which at some point I might be able to turn into an extension method. I accept this implemtation will bomb if the HttpContext.Current.Session is null as it should only be used in a web app.
The question is:
What is the best practice for such a registration in Autofac. I have seen a lot of mention about the use of nested containers etc. but no concrete examples, and I am keen to understand what might be wrong with the above approach (only thing I can think of is the automatic disposal stuff).
Thanks.
This looks fine.
Marking the component 'ExternallyOwned()' will ensure that Autofac doesn't call Dispose() on it.
The only gotchas here are that your session-scoped component could resolve dependencies of its own via the current container, and thus hold references to things that may belong to the current request (for instance.) This should be easy to spot in testing though.
When Instantiating a class, Windsor by default treats all public properties of the class as optional dependencies and tries to satisfy them. In my case, this creates a rather complicated circular dependency which causes my application to hang.
How can I explicitly tell Castle Windsor that it should not be trying to satisfy a public property? I assume there must be an attribute to that extent. I can't find it however so please let me know the appropriate namespace/assembly.
If there is any way to do this without attributes (such as Xml Configuration or configuration via code) that would be preferable since the specific library where this is happening has to date not needed a dependency on castle.
You can use the Castle.Core.DoNotWireAttribute attribute to stop a property from being wired up by the IoC container (this is in the Castle.Core assembly, which means your library only needs to take a dependency on the lightweight Castle.Core assembly - if for example you want to use the code without an inversion of control container altogether, or in a different IoC container).
I don't believe there's any way to prevent wiring from occurring in the Xml configuration, but it would be reasonably easy to add support for this - if I had to do this I would probably:
Introduce some kind of attribute on the property declaration in the xml: <myprop wire="false" />
Inherit from PropertiesDependenciesModelInspector, overriding the InspectProperties method to apply some additional logic to identifying which properties should be added as dependencies to the components model (inspecting the model.Configuration for the wire="false" attribute/value pair).
Inherit from DefaultComponentModelBuilder and override the InitializeContributors to include your replacement PropertiesDependenciesModelInspector - or just remove the existing properties contributor and add your own at run time via the AddContributor/RemoveContributor methods.
Replace the ComponentModelBuilder service instance assigned to the kernel of your container.
Another approach which could work for you is to just manually remove the dependencies from the model before any instances of the service are requested ie.
kernel.GetHandler(typeof(MyComponent)).ComponentModel.Dependencies.RemoveAll(d => d.DependencyKey == "PropertyThatShouldNotBeWired");
YMMV with that approach though - especially if you have startable services or other facilities which may be eagerly instantiating your component after it's registered.
I created a facility to help with this:
Castle.Facilities.OptionalPropertyInjection
I do not know which version of Castle you guys were using at that time, but none of the solution mentioned were working. Plus, there is a lot of dead links.
With castle 3.1, here the solution I came up with (thanks to some castle source code digging):
container.Register(Component.For(type)
.LifestyleTransient()
.Properties( propertyInfo => propertyInfo.PropertyType != typeof(MyOtherType)));
The 'Properties' function adds a property filter used by castle when constructing the ComponentModel. In my case, all properties dependency will be satisfied except the property type 'MyOtherType'.
Maybe it will be helpful for someone. In Windsor 4.1 there is PropertiesIgnore method during registration.
Component.For<Role>().LifestyleTransient().PropertiesIgnore((model, propertyInfo) => true)
DoNotWireAttribute
Class: http://svn.castleproject.org:8080/svn/castle/trunk/Core/Castle.Core/Attributes/DoNotWireAttribute.cs
Test: http://svn.castleproject.org:8080/svn/castle/trunk/InversionOfControl/Castle.Windsor.Tests/IgnoreWireTestCase.cs
This can be achieved by the following code:
var container = new WindsorContainer();
// We don't want to inject properties, only ctors
var propInjector = container.Kernel.ComponentModelBuilder
.Contributors
.OfType<PropertiesDependenciesModelInspector>()
.Single();
container.Kernel.ComponentModelBuilder.RemoveContributor(propInjector);
Source Castle Windsor Documentation
Posted this on the google groups forum too here: http://groups.google.com/group/castle-project-devel/browse_thread/thread/43aa513817bd057a