Description: This article is a reference to a collation of the article, do a record, basically no translation, please see the original text for details.
Key points to use note:
AUTOFAC would track every disposable component instance the IT creates, no matter how this instance is requested.
Don ' t resolve from the root container. Always resolve from and then release a lifetime scope.
Not recommended or suitable for use:
One
interface Imyresource {...} class Myresource:imyresource, IDisposable {...}
When an instance of myresource
was created in an AUTOFAC container, the container would hold a reference to it even when it was No longer being used by the rest of the program. This means, the garbage collector would be a unable to reclaim the memory held by that component, so the following progra M'll eventually exhaust all available memory and crash
var builder = new Containerbuilder (); builder. Registertype <MyResource> (). As<imyresource> (); using (var container = builder. Build ()) { while (true ) var r = Container. Resolve<imyresource> (); // Out of memory! }
His was a far cry from typical CLR behaviour, which are one more reason why it's good to get away from thinking on an Io C Container as a replacement new
for. If we ' d just created MyResource
directly in the loop, there wouldn ' t is any problem at all while (tru E) varnew// Fine, feed the GC
Two
Interface Imyservice {} class mycomponent:imyservice{ // Dependency on a service provided by a disposable component
public mycomponent (Imyresource Resource) {...}}
If A second component is resolved this depends on a service provided by a disposable component, the memory leak still OCCU Rs
while (true) // still holds instances of MyResource var s = container. Resolve<imyservice> ();
Three
Interfaceimyservice2{voidGo ();}classmycomponent2:imyservice2{Func<IMyResource>_resourcefactory; PublicMyComponent (func<imyresource>resourcefactory) {_resourcefactory=resourcefactory; } Public voidGo () { while(true) varR = _resourcefactory ();//still out of memory. }}
Is there any way to improve the situation above?
Answer: Lifetime Scopes
// var container = ... while (true) { using (var lifetimescope = container. Beginlifetimescope ()) { var r = lifetimescope.resolve<imyresource>(); // R, all of it dependencies and any other components // created indirectly 'll be released here }}
Lifetime Scopes can be used in a nested set:
var ls1 = container. Beginlifetimescope (); var ls2 = LS1. Beginlifetimescope (); // LS1 is a child of the container, LS2 are a child of LS1
Lifetime Scopes does not produce contextual dependencies:
var ls1 = container. Beginlifetimescope (); var ls2 = container. Beginlifetimescope (); // LS1 and LS2 is completely independent of each other
Owned Instance:
Owned instances () is the last Owned<T>
tale in Autofac's lifetime story.
An owned instance are a component that comes wrapped in its own lifetime scope. This makes it easier-keep track of what a component should be released, especially if it's used outside of a using
stat Ement.
To get a owned instance providing service T
, you can resolve one directly from the container
var ownedservice = container. Resolve<owned<imyservice>> ();
In lifetime terms, this is equivalent to creating a new lifetime scope from the container, and resolving from IMyService
. The only difference is, the and the IMyService
lifetime scope, holds it come wrapped up together in a single object.
The service implementation is available through the property Value
:
// Value is ImyserviceownedService.Value.DoSomething ();
When the owned instance are no longer needed, it and all of their disposable dependencies can be released by disposing the object:
Ownedservice.dispose ();
Owner Instance is used in conjunction with fun:
Components that is returned from Func<T>
delegates is associated with the same lifetime scope as the delegate its Elf. If that component was itself contained in a lifetime scope, and it creates a finite number of instances through the Delegat E, then there ' s no problem–everything would be cleaned on when the scope completes.
If the component calling the delegate is a long-lived one and then the instances returned from the delegate would need to be C leaned up eagerly. To does this, Owned<T>
can is used as the return value of a factory delegate
classmycomponent2:imyservice2{Func<Owned<IMyResource>>_resourcefactory; PublicMyComponent (func<owned<imyresource>>resourcefactory) {_resourcefactory=resourcefactory; } Public voidGo () { while(true) using(varR =_resourcefactory ())//Use r.value before disposing it }}
Func<T>
And Owned<T>
can be combined with other relationship types to define relationships with a clearer intent than just taking a D Ependency onILifetimeScope
Reference article:
http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/
http://nblumhardt.com/2010/01/the-relationship-zoo/
About the use of AUTOFAC traps