What Autofac LifetimeScope is assumed when registering a delegate? - autofac

I haven't been able to determine this from the documentation.
Given a registration:
builder.RegisterType<ExampleComponent>().As<IComponent>().InstancePerLifetimeScope();
What LifetimeScope will be assumed by the following registration?
builder.Register(ctx =>
{
var component = ctx.Resolve<IComponent>();
return new SomeService(component);
}).As<ISomeService>();
Note: This is just an example. Obviously in this case you'd just resolve ISomeService and allow Autofac to instantiate an instance of SomeService with the IComponent dependency. I have a more complex registration need for which this approach is necessary, but whose details aren't really pertinent to the question.
Given IComponent is registered as InstancePerLifetimeScope (which I understand to mean that it inherits the scope used to resolve this directly or the scope used to resolve a component for which this is a dependency), and that the delegate registered for ISomeService will be the default lifetime scope of InstancePerDependency, I would expect that the resolve of IComponent within the delegate would be with lifetime scope InstancePerDependency.
Is this correct?

When you resolve ISomeService, this will be done per dependency as expected, which means that you will get a new instance of SomeService on every resolve (by calling the delegate).
However, the call to get component eg:
var component = ctx.Resolve<IComponent>();
Will return one instance of component shared per lifetime scope (so if you do not create any child/nested lifetime scope(s), it will be more or less a singleton).
Here is a small example to demonstrate it.
First here is a simple implementation for IComponent:
public interface IComponent
{
int GetId();
}
public class ExampleComponent : IComponent
{
private static int id = 0;
private int instanceId;
public ExampleComponent()
{
this.instanceId = id;
id++;
}
public int GetId()
{
return this.instanceId;
}
}
Then for ISomeService :
public interface ISomeService
{
int GetServiceID();
int GetComponentId();
}
public class SomeService : ISomeService
{
private static int id = 0;
private int instanceId;
private readonly IComponent component;
public SomeService(IComponent component)
{
if (component == null)
throw new ArgumentNullException("component");
this.component = component;
this.instanceId = id;
id++;
}
public int GetComponentId()
{
return this.component.GetId();
}
public int GetServiceID()
{
return this.instanceId;
}
}
I kept registration as you wrote:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ExampleComponent>().As<IComponent>().InstancePerLifetimeScope();
builder.Register(ctx =>
{
var component = ctx.Resolve<IComponent>();
return new SomeService(component);
}).As<ISomeService>();
IContainer rootContainer = builder.Build();
And now let's do some resolve :
ISomeService service1 = rootContainer.Resolve<ISomeService>();
ISomeService service2 = rootContainer.Resolve<ISomeService>();
Console.WriteLine(string.Format("Service 1: {0} , Component : {1} ", service1.GetServiceID(), service1.GetComponentId()));
Console.WriteLine(string.Format("Service 2: {0} , Component : {1} ", service2.GetServiceID(), service2.GetComponentId()));
You will get:
Service 1: 0 , Component : 0
Service 2: 1 , Component : 0
Since Component is shared by the main lifetime scope.
Now of course, if you create child scopes:
IContainer rootContainer = builder.Build();
ILifetimeScope scope1 = rootContainer.BeginLifetimeScope();
ILifetimeScope scope2 = rootContainer.BeginLifetimeScope();
ISomeService service1 = scope1.Resolve<ISomeService>();
ISomeService service2 = scope2.Resolve<ISomeService>();
Console.WriteLine(string.Format("Service 1: {0} , Component : {1} ", service1.GetServiceID(), service1.GetComponentId()));
Console.WriteLine(string.Format("Service 2: {0} , Component : {1} ", service2.GetServiceID(), service2.GetComponentId()));
Service 1: 0 , Component : 0
Service 2: 1 , Component : 1
In that case, you have 2 different scopes, so each resolve to component will provide a different one.

Related

Autofac - InstancePerLifetimeScope vs InstancePerRequest in Application_Start in ASP.NET Web Forms

I am using Autofac With ASP.NET Webforms. I would like to understand the difference between InstancePerLifetimeScope and InstancePerRequest when i register dependencies in the App_Start method of the global.asx.
It look like that for both of them a new instance of the dependency is created just once at Every HttpRequest (verified with a breakpoint into the constructor of the dependency and with the HashCode of the object).
Any ideas?
Thank you
#Travis gave good link to the documentation describing how it works. However, I prefer to give examples additionally to illustrate the theory better. So, let's take a look at simple example.
Suppose you have two classes ClassA and ClassB implementing some simple interfaces IClassA and IClassB.
public class ClassA : IClassA
{
public ClassA() {
}
}
public class ClassB : IClassB
{
public ClassB() {
}
}
Now, let's see what happens when we register them in different ways.
Example A
builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IClassA>().InstancePerLifetimeScope();
builder.RegisterType<ClassB>().As<IClassB>().InstancePerLifetimeScope();
Then, in the controller, you do this:
public class HomeController : Controller
{
private readonly IClassA _classA;
private readonly IClassB _classB;
private readonly IComponentContext _ctx;
public HomeController(IClassA classA, IClassB classB, IComponentContext ctx) {
_classA = classA;
_classB = classB;
_ctx = ctx;
}
public string Get() {
using (var scope = _ctx.BeginLifetimeScope()) {
var newClassA = scope.Resolve<IClassA>(); // Object.ReferenceEquals(newClassA, _classA) == false
var newClassB = scope.Resolve<IClassB>(); // Object.ReferenceEquals(newClassB, _classB) == false
return "Ok";
}
}
}
In this example both 'new' variables in Get() method will receive new instances since they are both registered to be unique per lifetime scope. We began new lifetime scope - we got new instances.
Now, let's take a look at another example.
Example B
builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IClassA>().InstancePerLifetimeScope();
builder.RegisterType<ClassB>().As<IClassB>().InstancePerRequest(); // now they have different life time!
// controller:
public class HomeController : Controller
{
private readonly IClassA _classA;
private readonly IClassB _classB;
private readonly IComponentContext _ctx;
public HomeController(IClassA classA, IClassB classB, IComponentContext ctx) {
_classA = classA;
_classB = classB;
_ctx = ctx;
}
public string Get() {
using (var scope = _ctx.BeginLifetimeScope()) {
var newClassA = scope.Resolve<IClassA>(); // Object.ReferenceEquals(newClassA, _classA) == false
var newClassB = scope.Resolve<IClassB>(); // Object.ReferenceEquals(newClassB, _classB) == true
return "Ok";
}
}
}
See what happened here? Even though we began new lifetime scope - ClassB still gets resolved from request scope and not from our new one. This is the difference between InstancePerLifetimeScope() and InstancePerRequest().
And as documentation suggests, internally it is based on another Autofac concept - InstancePerMatchingLifetimeScope().
In many cases it amounts to the same thing. This is an FAQ on the Autofac doc site.

How to initialize and use Custom / Support classes in MVC 6 with Asp.Net Core 2.0

public sealed class SessionContext
{
private ISession httpContext;
public SessionContext(ISession httpContext)
{
this.httpContext = httpContext;
}
public string UserType
{
get
{
return httpContext.GetString("_UserType");
}
set
{
httpContext.SetString("_UserType", value);
}
}
...... More properties .....
}
public class HomeController : Controller
{
private AppSettings _appSettings;
private SessionContext session = null;
private readonly IHttpContextAccessor _httpContextAccessor;
private ISession httpContext => _httpContextAccessor.HttpContext.Session;
//I don't like this constructor as it is getting initialize or every controller call.
public HomeController(IOptions<AppSettings> myAppSettings, IHttpContextAccessor httpContextAccessor)
{
_appSettings = myAppSettings.Value;
_httpContextAccessor = httpContextAccessor;
appSettings = new AppSettings(_appSettings); //Should initialize only once.
session = new SessionContext(httpContext);
}
}
I have questions regarding ...
How to initialize and use Custom / Support classes in MVC 6 with Asp.Net Core 2.0
When I Initialize these classes, they getting initialize or every controller call. That is very redundant.
my SessionContext class is getting re-initialize every time. So I am loosing the values when I call this class from another controller.
I tried this approach but, not much of use.
services.AddSingleton();
Move from question to answer:
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddSingleton<SessionContext, SessionContext>();
//calling the extension class to instantiate the classes which we require earlier.
services.AddMyProjectHelper(Configuration)
}
Created a extension class... where it initializes the support classes
public static class MyProjectHelperExtensions
{
public static IServiceCollection AddMyProjectHelper(this IServiceCollection services, IConfiguration configuration)
{
var section = configuration.GetSection("AppSettings");
// we first need to create an instance
var settings = new AppSettings();
// then we set the properties
new ConfigureFromConfigurationOptions<AppSettings>(section).Configure(settings);
var session = services.BuildServiceProvider().GetService<SessionContext>();
// then we register the instance into the services collection
services.AddSingleton<MyProjectHelper>(new MyProjectHelper(settings, session));
return services;
}
}
finally controller ctor uses the DI for the required class. Now I have avoided redundant initialization of support classes.
public SecurityController(MyProjectHelper objHelper, SessionContext sessionContext)
{
session = sessionContext;
projectHelper = projectHelper ?? objHelper;
}
Now, I am able to share the session variables which I have set in my support classes
private SessionContext session = null;
public HomeController(SessionContext sessionContext)
{
session = sessionContext;
}
[Authorize]
public IActionResult Index()
{
if (session.CurrEmployee != null)
{
ViewBag.Name = (session.CurrEmployee.FirstName + " " + session.CurrEmployee.LastName);
return View();
}
}

Autofac: cannot resolve dependency using factory after ContainerBuilder.Update()

My problem is that I want to use Func<> factory to resolve dependency. And in if I use ContainerBuilder Update() (I need it for mocking some services in integration tests), this factories still resolve outdated instances.
I created simple scenario to reproduce the problem:
class Program
{
static void Main(string[] args)
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Test>().As<ITest>();
containerBuilder.RegisterType<Test1Factory>().As<ITestFactory>();
containerBuilder.RegisterType<TestConsumer>().AsSelf();
var container = containerBuilder.Build();
var tc1 = container.Resolve<TestConsumer>();
var cbupdater = new ContainerBuilder();
cbupdater.RegisterType<Test2>().As<ITest>();
cbupdater.RegisterType<Test2Factory>().As<ITestFactory>();
cbupdater.Update(container);
var tc2 = container.Resolve<TestConsumer>();
Console.ReadLine();
}
}
public interface ITest
{
int Id { get; set; }
}
public class Test : ITest
{
public Test()
{
Id = 1;
}
public int Id { get; set; }
}
public class Test2 : ITest
{
public Test2()
{
Id = 2;
}
public int Id { get; set; }
}
public interface ITestFactory
{
ITest Create();
}
public class Test1Factory : ITestFactory
{
public ITest Create()
{
return new Test();
}
}
public class Test2Factory : ITestFactory
{
public ITest Create()
{
return new Test2();
}
}
public class TestConsumer
{
public TestConsumer(Func<ITest> testFactory, ITest test, ITestFactory customFactory)
{
Console.WriteLine("factory: " + testFactory().Id);
Console.WriteLine("direct: " + test.Id);
Console.WriteLine("MyCustomFactory: " + customFactory.Create().Id);
Console.WriteLine("*************");
Console.WriteLine();
}
}
The output is:
factory: 1 direct: 1 MyCustomFactory: 1
factory: 1 direct: 2 MyCustomFactory: 2
Notice "factory: 1" in both cases.
Am I missing something or I have to create my cusom factory in this scenario?
P.S.
Autofac 3.5.2 or 4.0 beta 8-157
.net 4.5.1
That's by design unfortunately, the reasons, I don't know. Looking at the Autofac code gives you a better insight on how they register items with the same interface definition, in short, all registrations are maintained but the last registration wins (ref). Wait...that's not all, weirdly, for Fun<...>, you actually get them in order. You can easily test by changing the constructor of the TestConsumer class to:
public TestConsumer(Func<ITest> testFactory, IEnumerable<Func<ITest>> testFactories, IEnumerable<ITest> tests, ITest test, ITestFactory customFactory)
{
// ...
}
Note that you get all the Funcs and the ITest registration. You are simply lucky that resolving ITest directly resolves to Test2.
Now, having said all of the above, there is a way described here. You have to create a container without the registration you want to override, therefore:
/// <summary>
/// This has not been tested with all your requirements
/// </summary>
private static IContainer RemoveOldComponents(IContainer container)
{
var builder = new ContainerBuilder();
var components = container.ComponentRegistry.Registrations
.Where(cr => cr.Activator.LimitType != typeof(LifetimeScope))
.Where(cr => cr.Activator.LimitType != typeof(Func<ITest>));
foreach (var c in components)
{
builder.RegisterComponent(c);
}
foreach (var source in container.ComponentRegistry.Sources)
{
builder.RegisterSource(source);
}
return builder.Build();
}
And you can simply change your main method to the following:
static void Main(string[] args)
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Test>().As<ITest>();
containerBuilder.RegisterType<Test1Factory>().As<ITestFactory>();
containerBuilder.RegisterType<TestConsumer>().AsSelf();
var container = containerBuilder.Build();
var tc1 = container.Resolve<TestConsumer>();
container = RemoveOldComponents(container);
var cbupdater = new ContainerBuilder();
cbupdater.RegisterType<Test2>().As<ITest>();
cbupdater.RegisterType<Test2Factory>().As<ITestFactory>();
cbupdater.Update(container);
var tc2 = container.Resolve<TestConsumer>();
Console.ReadLine();
}
PS: Wouldn't it be great to have a method which does the exact opposite of PreserveExistingDefaults()

How do I pass a parameter to the constructor using Simple Injector?

Does Simple Injector allow you to pass parameters to constructor when you resolve? I'd like to know if both these frameworks do what Unity's ResolverOverride or DependencyOverride both do.
I suspect that this question is about passing primitive values to the constructor at the time the service is actually resolved.
Let's set up a simple test class:
public interface IFoo
{
}
public class Foo : IFoo
{
public Foo(string value)
{
}
}
The Foo class takes a string argument that we would like to supply when resolving the IFoo service.
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
var firstFoo = container.GetInstance<string, IFoo>("SomeValue");
var secondFoo = container.GetInstance<string, IFoo>("AnotherValue");
If we want to be able to create new instances of the Foo class without using the container directly, we can simply inject a function delegate.
public interface IBar { }
public class Bar : IBar
{
public Bar(Func<string, IFoo> fooFactory)
{
var firstFoo = fooFactory("SomeValue");
var secondFoo = fooFactory("AnotherValue");
}
}
The "composition root" now looks like this:
var container = new ServiceContainer();
container.Register<string, IFoo>((factory, value) => new Foo(value));
container.Register<IBar, Bar>();
var bar = container.GetInstance<IBar>();
If the question is about passing a "static" primitive value to the contructor, this is simply done by registering a factory delegate like this.
var container = new ServiceContainer();
container.Register<IFoo>((factory) => new Foo("SomeValue"));
var firstInstance = container.GetInstance<IFoo>();
var secondInstance = container.GetInstance<IFoo>();
The difference is that this approach does not let you pass a value at resolve time. The value is statically specified at registration time.
Probably the easiest option with Simple Injector is to register with a delegate
[Test]
public void Test1()
{
Container container = new Container();
container.Register<IClassWithParameter>(() => new ClassWithParameter("SomeValue"));
var result = container.GetInstance<IClassWithParameter>();
}
public interface IClassWithParameter { }
public class ClassWithParameter : IClassWithParameter
{
public ClassWithParameter(string parameter)
{
}
}
An advanced option for injecting primitive dependencies is detailed here
The above will all work if your constructor does not have any other dependencies (or you want to resolve these dependencies manually). If you have the scenario below though it falls down:
public class Test : ITest
{
private IFoo _foo;
public Test(string parameter, IFoo foo)
{
_foo = foo;
....
}
}
Now you not only have to manually inject the string but also Foo. So now your not using dependancy injection at all (really). Also Simple Injector state:
Simple Injector does not allow injecting primitive types (such as
integers and string) into constructors.
My reading of this is that they're saying "don't do this".
Extensibillity points
Another option here is to use "Extensibillity points" for this scenario.
To do this you need to abstract your hard coded elements from your injected elements:
public class Test : ITest
{
private IFoo _foo;
public Test(IFoo foo)
{
_foo = foo;
....
}
public void Init(string parameter)
{
}
}
You can now inject your dependanices and your hardcoded elements:
_container.Register<ITest, Test>();
_container.RegisterInitializer<Test>(instance => {instance.Init("MyValue");});
If you now add another dependancy, your injection will now work without you having to update the config, i.e. your code is nicely de-coupled still:
public class Test : ITest
{
private IFoo _foo;
private IBar _bar;
public Test(IFoo foo, IBar bar)
{
_foo = foo;
_bar = bar;
....
}
public void Init(string parameter)
{
}
}
In response to Liam's answer I would like to point out that there is a simpler way of doing this.
If you have the following situation:
public class Test : ITest
{
private IFoo _foo;
public Test(IFoo foo, string parameter)
{
_foo = foo;
....
}
}
You could write your ioc configuration as below
_container.Register<IFoo, Foo>();
_container.Register<ITest>(
() => new Test(
_container.GetInstance<IFoo>(),
"MyValue"
)
);

Autofac LifetimeScope with BeginLifetimeScope not working

I am trying to evaluate the scoping of Autofac and as I understand it, when an instance has been declared as InstancePerLifetimeScope, then within the using(container.BeginLifetimeScope()) block, we should get the same instance. But in another such block, we should get a different instance. But my code (in linqpad) gives me the same instance. Windsor's lifestylescope however works as I think it should.
Code:
static IContainer glkernel;
void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Controller>();
builder.RegisterType<A>().As<IInterface>().InstancePerLifetimeScope();
glkernel = builder.Build();
using (glkernel.BeginLifetimeScope()){
Controller c1 = glkernel.Resolve<Controller>();
c1.GetA();//should get instance 1
c1.GetA();//should get instance 1
}
using (glkernel.BeginLifetimeScope()){
Controller d = glkernel.Resolve<Controller>();
d.GetA();//should get instance 2
d.GetA();//should get instance 2
}
}
public interface IInterface
{
void DoWork(string s);
}
public class A : IInterface
{
public A()
{
ID = "AAA-"+Guid.NewGuid().ToString().Substring(1,4);
}
public string ID { get; set; }
public string Name { get; set; }
public void DoWork(string s)
{
Display(ID,"working...."+s);
}
}
public static void Display(string id, string mesg)
{
mesg.Dump(id);
}
public class Controller
{
public Controller()
{
("controller ins").Dump();
}
public void GetA()
{
//IInterface a = _kernel.Resolve<IInterface>();
foreach(IInterface a in glkernel.Resolve<IEnumerable<IInterface>>())
{
a.DoWork("from A");
}
}
}
The output is:
controller ins
AAA-04a0
working....from A
AAA-04a0
working....from A
controller ins
AAA-04a0
working....from A
AAA-04a0
working....from A
Perhaps my understanding of scoping is wrong. If so, can you please explain.
What do I have to do to get a different instance in the second block?
The problem is you're resolving things out of the container - the glkernel instead of out of the lifetime scope. A container is a lifetime scope - the root lifetime scope.
Resolve out of the lifetime scope instead. That may mean you need to change up your controller to pass in the list of components rather than using service location.
public class Controller
{
private IEnumerable<IInterface> _interfaces;
public Controller(IEnumerable<IInterface> interfaces)
{
this._interfaces = interfaces;
("controller ins").Dump();
}
public void GetA()
{
foreach(IInterface a in this._interfaces)
{
a.DoWork("from A");
}
}
}
Then it's easy enough to switch your resolution code.
using (var scope1 = glkernel.BeginLifetimeScope()){
Controller c1 = scope1.Resolve<Controller>();
c1.GetA();
c1.GetA();
}
using (var scope2 = glkernel.BeginLifetimeScope()){
Controller c2 = scope2.Resolve<Controller>();
c2.GetA();
c2.GetA();
}
The Autofac wiki has some good information on lifetime scopes you might want to check out.