autofac instance initialization notification - autofac

Is there a way to determine when Autofac has completed an initialization of an instance?
You may need it if you have Lazy dependencies, or you inject dependencies via properties.
Possible solution might look like this:
public class Component : IKeepMeInformed {
private readonly IOtherComponent otherComponent;
public class Component(Lazy<IOtherComponent> otherComponent) {
this.otherComponent = otherComponent;
}
void IKeepMeInformed.InitializationCompleted() {
// Do whatever you need with this.otherComponent.Value
}
}

Not directly tied to Lazy components, but Autofac exposes events that lets you hook into the lifetime of instances. Listening for the OnActivated event will enable you to do stuff immediately after an instance have been created. E.g.:
builder.RegisterType<OtherComponentImplementation>().As<IOtherComponent>()
.OnActivated(e => InitializationCompleted(e.Instance));
Update: actually, in the context of your Component class, you should "know" when the instance is initialized. It will be whenever you access the Lazy<>.Value property first.

Related

Extenject - NullReferenceException when second time inject

I'm new at Zenject(Extenject).
My dev environment: Win10, Unity2020, Extenject 9.2.0
Here is my question:
In installer bind the class
Container.Bind<AccountInfo>().AsCached();
Inject it at classA
private AccountInfo accountInfo;
[Inject]
private void Init(GameSetup _gameSetup, AccountInfo _accountInfo)
{
this.gameSetup = _gameSetup;
this.accountInfo = _accountInfo;
}
accountInfo.address = "xxx'; // works fine
Then inject AccountInfo to classB
private AccountInfo accountInfo;
[Inject]
private void Init(AccountInfo _accountInfo)
{
this.accountInfo = _accountInfo;
}
accountInfo.address = "xxx'; //NullReferenceException: Object reference not set to an instance of an object
Why accountInfo changed to null? AsCached() dosen't work? Or something worng else?
Help please~~ Thank you!
Here is my code:
Installer
"ClassA" inject GameSetup, and create instance, works fine
"ClassB" inject GameSetup, Error: null object
"ClassB" Creator, I'm trying use container.Instantiate() to create it
---update---
gameSetup still Null Object
There are two cases, when injection will not work properly in your code.
The code, that uses injected object is executed before Init. For example if this code is placed in the construcor.
You create your GameObject/Component in runtime whithout using IInstantiator. While you use Znject you always should use IInstantiator to create objects. To do it you should inject IInstantiator to the object, that creates another objects. IItstantiator is always binded in the container by default, so you don't have to bind it manually. For example:
public class Creator : MonoBehaviour {
[SerializeField]
private GameObject _somePrefab;
private IInstantiator _instantiator;
[Inject]
public void Initialize(IInstantiator instantiator) {
_instantiator = instantiator;
}
private void Start() {
// example of creating components
var gameObj = new GameObject(); // new empty gameobjects can be created without IInstantiator
_instantiator.InstantiateComponent<YourComponentClass>(gameObj);
// example of instantiating prefab
var prefabInstance = _instantiator.InstantiatePrefab(_somePrefab);
}
}
Not an expert but I think that passing IInstantiator or the container around is not a good practice. If you need to create injected instances at runtime, then you need a Factory.
From the documentation
1.- Best practice with DI is to only reference the container in the composition root "layer"
Note that factories are part of this layer and the container can be referenced there (which is necessary to create objects at runtime).
2.- "When instantiating objects directly, you can either use DiContainer or you can use IInstantiator, which DiContainer inherits from. However, note that injecting the DiContainer is usually a sign of bad practice, since there is almost always a better way to design your code such that you don't need to reference DiContainer directly".
3.- "Once again, best practice with dependency injection is to only reference the DiContainer in the "composition root layer""

How to resolve InstancePerLifetimeScope component from within SingleInstace component via Func?

The idea is just simple and works in the other containers, not limited with .Net:
Singleton component being referenced from within request context references transient component which in turn references request-scoped component (some UnitOfWork).
I expected that Autofac would resolve the same scoped component in both cases:
- when I request it directly from request scope
- when I request it by invoking Func<>
Unfortunately the reality is quite a bit different - Autofac sticks SingleInstance component to the root scope and resolves InstancePerLifetimeScope component on
the root component introducing memory leak (!!!) as UnitOfWork is disposable and becomes tracked by root scope (attempt to use matching web request scope would just fail finding request scope which is yet more misleading).
Now I'm wondering whether such behavior is by design or just a bug? If it is by design I'm not sure what are the use cases and why it differs from the other containers.
The example is as follows (including working SimpleInjector case):
namespace AutofacTest
{
using System;
using System.Linq;
using System.Linq.Expressions;
using Autofac;
using NUnit.Framework;
using SimpleInjector;
using SimpleInjector.Lifestyles;
public class SingletonComponent
{
public Func<TransientComponent> Transient { get; }
public Func<ScopedComponent> Scoped { get; }
public SingletonComponent(Func<TransientComponent> transient, Func<ScopedComponent> scoped)
{
Transient = transient;
Scoped = scoped;
}
}
public class ScopedComponent : IDisposable
{
public void Dispose()
{
}
}
public class TransientComponent
{
public ScopedComponent Scoped { get; }
public TransientComponent(ScopedComponent scopedComponent)
{
this.Scoped = scopedComponent;
}
}
class Program
{
static void Main(string[] args)
{
try
{
AutofacTest();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
try
{
SimpleInjectorTest();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AutofacTest()
{
var builder = new ContainerBuilder();
builder.RegisterType<ScopedComponent>().InstancePerLifetimeScope();
builder.RegisterType<SingletonComponent>().SingleInstance();
builder.RegisterType<TransientComponent>();
var container = builder.Build();
var outerSingleton = container.Resolve<SingletonComponent>();
using (var scope = container.BeginLifetimeScope())
{
var singleton = scope.Resolve<SingletonComponent>();
Assert.That(outerSingleton, Is.SameAs(singleton));
var transient = scope.Resolve<TransientComponent>();
var scoped = scope.Resolve<ScopedComponent>();
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
// this fails
Assert.That(singleton.Transient().Scoped, Is.SameAs(scoped));
Assert.That(transient.Scoped, Is.SameAs(scoped));
Assert.That(singleton.Scoped(), Is.SameAs(scoped)); // this fails
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
}
}
private static void SimpleInjectorTest()
{
var container = new SimpleInjector.Container();
container.Options.AllowResolvingFuncFactories();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.Register<ScopedComponent>(Lifestyle.Scoped);
container.Register<SingletonComponent>(Lifestyle.Singleton);
container.Register<TransientComponent>(Lifestyle.Transient);
container.Verify();
var outerSingleton = container.GetInstance<SingletonComponent>();
using (var scope = AsyncScopedLifestyle.BeginScope(container))
{
var singleton = container.GetInstance<SingletonComponent>();
Assert.That(outerSingleton, Is.SameAs(singleton));
var transient = container.GetInstance<TransientComponent>();
var scoped = container.GetInstance<ScopedComponent>();
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
Assert.That(singleton.Transient().Scoped, Is.SameAs(scoped));
Assert.That(transient.Scoped, Is.SameAs(scoped));
Assert.That(singleton.Scoped(), Is.SameAs(scoped));
Assert.That(singleton.Transient(), Is.Not.SameAs(transient));
}
}
}
public static class SimpleInjectorExtensions
{
public static void AllowResolvingFuncFactories(this ContainerOptions options)
{
options.Container.ResolveUnregisteredType += (s, e) =>
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>))
{
return;
}
Type serviceType = type.GetGenericArguments().First();
InstanceProducer registration = options.Container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
};
}
}
}
The short version what you're seeing is not a bug, you're just misunderstanding some of the finer points of lifetime scopes and captive dependencies.
First, a couple of background references from the Autofac docs:
Controlling Scope and Lifetime explains a lot about how lifetime scopes and that hierarchy works.
Captive Dependencies talks about why you don't generally shouldn't take an instance-per-lifetime or instance-per-dependency scoped item into a singleton.
Disposal talks about how Autofac auto-disposes IDisposable items and how you can opt out of that.
Implicit Relationship Types describes the Owned<T> relationship type used as part of the IDisposable opt-out.
Some big key takeaways from these docs that directly affect your situation:
Autofac tracks IDisposable components so they can be automatically disposed along with the lifetime scope. That means it will hold references to any resolved IDisposable objects until the parent lifetime scope is resolved.
You can opt out of IDisposable tracking either by registering the component as ExternallyOwned or by using Owned<T> in the constructor parameter being injected. (Instead of taking in an IDependency take in an Owned<IDependency>.)
Singletons live in the root lifetime scope. That means any time you resolve a singleton it will be resolved from the root lifetime scope. If it is IDisposable it will be tracked in the root lifetime scope and not released until that root scope - the container itself - is disposed.
The Func<T> dependency relationship is tied to the same lifetime scope as the object in which it's injected. If you have a singleton, that means the Func<T> will resolve things from the same lifetime scope as the singleton - the root lifetime scope. If you have something that's instance-per-dependency, the Func<T> will be attached to whatever scope the owning component is in.
Knowing that, you can see why your singleton, which takes in a Func<T>, keeps trying to resolve these things from the root lifetime scope. You can also see why you're seeing a memory leak situation - you haven't opted out of the disposal tracking for the things that are being resolved by that Func<T>.
So the question is, how do you fix it?
Option 1: Redesign
Generally speaking, it would be better to invert the relationship between the singleton and the thing you have to resolve via Func<T>; or stop using a singleton altogether and let that be a smaller lifetime scope.
For example, say you have some IDatabase service that needs an IPerformTransaction to get things done. The database connection is expensive to spin up, so you might make that a singleton. You might then have something like this:
public class DatabaseThing : IDatabase
{
public DatabaseThing(Func<IPerformTransaction> factory) { ... }
public void DoWork()
{
var transaction = this.factory();
transaction.DoSomethingWithData(this.Data);
}
}
So, like, the thing that's expensive to spin up uses a Func<T> to generate the cheap thing on the fly and work with it.
Inverting that relationship would look like this:
public PerformsTransaction : IPerformTransaction
{
public PerformsTransaction(IDatabase database) { ... }
public void DoSomethingWithData()
{
this.DoSomething(this.Database.Data);
}
}
The idea is that you'd resolve the transaction thing and it'd take the singleton in as a dependency. The cheaper item could easily be disposed along with child lifetime scopes (i.e., per request) but the singleton would remain.
It'd be better to redesign if you can because even with the other options you'll have a rough time getting "instance per request" sorts of things into a singleton. (And that's a bad idea anyway from both a captive dependency and threading standpoint.)
Option 2: Abandon Singleton
If you can't redesign, a good second choice would be to make the lifetime of the singleton... not be a singleton. Let it be instance-per-scope or instance-per-dependency and stop using Func<T>. Let everything get resolved from a child lifetime scope and be disposed when the scope is disposed.
I recognize that's not always possible for a variety of reasons. But if it is possible, that's another way to escape the problem.
Option 3: Use ExternallyOwned
If you can't redesign, you could register the disposable items consumed by the singleton as ExternallyOwned.
builder.RegisterType<ThingConsumedBySingleton>()
.As<IConsumedBySingleton>()
.ExternallyOwned();
Doing that will tell Autofac to not track the disposable. You won't have the memory leak. You will be responsible for disposing the resolved objects yourself. You will also still be getting them from the root lifetime scope since the singleton is getting a Func<T> injected.
public void MethodInsideSingleton()
{
using(var thing = this.ThingFactory())
{
// Do the work you need to and dispose of the
// resolved item yourself when done.
}
}
Option 4: Owned<T>
If you don't want to always manually dispose of the service you're consuming - you only want to deal with that inside the singleton - you could register it as normal but consume a Func<Owned<T>>. Then the singleton will resolve things as expected but the container won't track it for disposal.
public void MethodInsideSingleton()
{
using(var ownedThing = this.ThingFactory())
{
var thing = ownedThing.Value;
// Do the work you need to and dispose of the
// resolved item yourself when done.
}
}

GWT Editor framework

Is there a way to get the proxy that editor is editing?
The normal workflow would be:
public class Class implments Editor<Proxy>{
#Path("")
#UiField AntoherClass subeditor;
void someMethod(){
Proxy proxy = request.create(Proxy.class);
driver.save(proxy);
driver.edit(proxy,request);
}
}
Now if i got a subeditor of the same proxy
public class AntoherClass implements Editor<Proxy>{
someMethod(){
// method to get the editing proxy ?
}
}
Yes i know i can just set the proxy to the Child editor with setProxy() after its creation, but i want to know if there is something like HasRequestContext but for the edited proxy.
This usefull when you use for example ListEditor in non UI objects.
Thank you.
Two ways you can get a reference to the object that a given editor is working on. First, some simple data and a simple editor:
public class MyModel {
//sub properties...
}
public class MyModelEditor implements Editor<MyModel> {
// subproperty editors...
}
First: Instead of implementing Editor, we can pick another interface that also extends Editor, but allows sub-editors (LeafValueEditor does not allow sub-editors). Lets try ValueAwareEditor:
public class MyModelEditor2 implements ValueAwareEditor<MyModel> {
// subproperty editors...
// ValueAwareEditor methods:
public void setValue(MyModel value) {
// This will be called automatically with the current value when
// driver.edit is called.
}
public void flush() {
// If you were going to make any changes, do them here, this is called
// when the driver flushes.
}
public void onPropertyChange(String... paths) {
// Probably not needed in your case, but allows for some notification
// when subproperties are changed - mostly used by RequestFactory so far.
}
public void setDelegate(EditorDelegate<MyModel> delegate) {
// grants access to the delegate, so the property change events can
// be requested, among other things. Probably not needed either.
}
}
This requires that you implement the various methods as in the example above, but the main one you are interested in will be setValue. You do not need to invoke these yourself, they will be called by the driver and its delegates. The flush method is also good to use if you plan to make changes to the object - making those changes before flush will mean that you are modifying the object outside of the expected driver lifecycle - not the end of the world, but might surprise you later.
Second: Use a SimpleEditor sub-editor:
public class MyModelEditor2 implements ValueAwareEditor<MyModel> {
// subproperty editors...
// one extra sub-property:
#Path("")//bound to the MyModel itself
SimpleEditor self = SimpleEditor.of();
//...
}
Using this, you can call self.getValue() to read out what the current value is.
Edit: Looking at the AnotherEditor you've implemented, it looks like you are starting to make something like the GWT class SimpleEditor, though you might want other sub-editors as well:
Now if i got a subeditor of the same proxy
public class AntoherClass implements Editor<Proxy>{
someMethod(){
// method to get the editing proxy ?
}
}
This sub-editor could implement ValueAwareEditor<Proxy> instead of Editor<Proxy>, and be guaranteed that its setValue method would be called with the Proxy instance when editing starts.
In your child editor class, you can just implement another interface TakesValue, you can get the editing proxy in the setValue method.
ValueAwareEditor works too, but has all those extra method you don't really need.
This is the only solution I found. It involves calling the context edit before you call the driver edit. Then you have the proxy to manipulate later.

MEF and IObservables

I have a singleton IObservable that returns the results of a Linq query. I have another class that listens to the IObservable to structure a message. That class is Exported through MEF, and I can import it and get asynchronous results from the Linq query.
My problem is that after initial composition takes place, I don't get any renotification on changes when the data supplied to the Linq query changes. I implemented INotifyPropertyChanged on the singleton, thinking it word make the exported class requery for a new IObservable, but this doesn't happen.
Maybe I'm not understanding something about the lifetime of MEF containers, or about property notification. I'd appreciate any help.
Below are the singleton and the exported class. I've left out some pieces of code that can be inferred, like the PropertyChanged event handlers and such. Suffice to say, that does work when the underlying Session data changes. The singleton raises a change event for UsersInCurrentSystem, but there is never any request for a new IObservable from the UsersInCurrentSystem property.
public class SingletonObserver: INotifyPropertyChanged
{
private static readonly SingletonObserver _instance = new SingletonObserver();
static SingletonObserver() { }
private SingletonObserver()
{
Session.ObserveProperty(xx => xx.CurrentSystem, true)
.Subscribe(x =>
{
this.RaisePropertyChanged(() => this.UsersInCurrentSystem);
});
}
public static SingletonObserverInstance { get { return _instance; } }
public IObservable<User> UsersInCurrentSystem
{
get
{
var x = from user in Session.CurrentSystem.Users
select user;
return x.ToObservable();
}
}
}
[Export]
public class UserStatus : INotifyPropertyChanged
{
private string _data = string.Empty;
public UserStatus
{
SingletonObserver.Instance.UsersInCurrentSystem.Subscribe(sender =>
{
//set _data according to information in sender
//raise PropertyChanged for Data
}
}
public string Data
{
get { return _data; } }
}
}
My problem is that after initial composition takes place, I don't get any renotification on changes when the data supplied to the Linq query changes.
By default MEF will only compose parts once. When a part has been composed, the same instance will be supplied to all imports. The part will not be recreated unless you explicitly do so.
In your case, if the data of a part change, even if it implements INotifyPropertyChanged, MEF will not create a new one, and you don't need to anyway.
I implemented INotifyPropertyChanged on the singleton, thinking it word make the exported class requery for a new IObservable
No.
Maybe I'm not understanding something about the lifetime of MEF containers, or about property notification.
Property notification allows you to react to a change in the property and has no direct effect on MEF. As for the container's lifetime, it will remain active until it is disposed. While it is still active, the container will keep references to it's compose parts. It's actually a little more complex than that, as parts can have different CreationPolicy that affects how MEF holds the part, I refer you to the following page: Parts Lifetime for more information.
MEF does allow for something called Recomposition. You can set it likewise:
[Import(AllowRecomposition=true)]
What this does tough is allow MEF to recompose parts when new parts are available or existing parts aren't available anymore. From what I understand it isn't what you are referring to in your question.

Strong reference of Autofac 2

newbie here, sorry if this is an obvious question.
I've read from this page: http://code.google.com/p/autofac/wiki/NewInV2
In Autofac 1, weak references are held by the container. This makes sense if the objects being referenced use disposal to release GC/finalizer resources, but if the dispose method contains application logic then GC timing could introduce unexpected behaviour.
Autofac 2 holds normal references. To opt out of this behaviour and mange disposal manually, use the ExternallyOwned registration modifier.
Is that mean when I need to release an object that is resolved by Autofac to the GC, I cannot simply say:
a = null;
because Autofac holds a strong reference to the object. Instead, I should use Owned<>:
public class MyClass
{
public MyClass(Owned<A> a)
{
a.Value.Dosomething();
a.Dispose();
}
}
or use the ExternallyOwned registration modifier:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).ExternallyOwned();
later on, I should be able to use a = null to release the object to the GC.
Is that right?
Thanks!
By default, you don't need to dispose anything - Autofac will automatically identify and dispose any IDisposable instances it created when their containing lifetime scope is disposed.
You only need to use Owned<T> or ExternallyOwned() if you have a reason to manage the lifetime of the object manually. If you resolve an Owned<T> then you should call t.Dispose() yourself - the common usage pattern is to take a dependency on a factory delegate:
public class MyClass
{
private Func<Owned<User>> myDisposableFactory;
public MyClass(Func<Owned<User>> myDisposableFactory)
{
this.myDisposableFactory = myDisposableFactory;
}
public void DoSomething()
{
using (var disposable = this.myDisposableFactory())
{
// ...
disposable.Dispose();
}
}
}
If you register a type as ExternallyOwned() then Autofac will not dispose of any resolved instance when the containing lifetime scope ends - it's up to you to manage it.
Take a look at Nicholas Blumhardt's article on lifetimes for more information.