zoukankan      html  css  js  c++  java
  • 关于Autofac的使用陷阱

    说明:本文是对参考文章的一个整理,做一个记录,基本没有翻译,详情请参看原文.

    使用注意要点:

    Autofac will track every disposable component instance that it creates, no matter how that instance is requested.

    Don’t resolve from the root container. Always resolve from and then release a lifetime scope.

    不推荐、不宜的用法:

    一、

    interface IMyResource { … }
    
    class MyResource : IMyResource, IDisposable { … }


    When an instance of MyResource is created in an Autofac container, the container will hold a reference to it even when it is no longer being used by the rest of the program. This means that the garbage collector will be unable to reclaim the memory held by that component, so the following program will 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 is a far cry from typical CLR behaviour, which is one more reason why it is good to get away from thinking about an IoC container as a replacement for new. If we’d just created MyResource directly in the loop, there wouldn’t be any problem at all
    while (true)
        var r = new MyResource(); // Fine, feed the GC

    二、

    interface IMyService { }
    
    class MyComponent : IMyService
    {
        // Dependency on a service provided by a disposable component
        public MyComponent(IMyResource resource) { … }
    }

    If a second component is resolved that depends on a service provided by a disposable component, the memory leak still occurs
    while (true)
        // Still holds instances of MyResource
        var s = container.Resolve<IMyService>();

    三、

    interface IMyService2
    {
        void Go();
    }
    
    class MyComponent2 : IMyService2
    {
        Func<IMyResource> _resourceFactory;
    
        public MyComponent(Func<IMyResource> resourceFactory)
        {
            _resourceFactory = resourceFactory;
        }
    
        public void Go()
        {
            while (true)
                var r = _resourceFactory(); // Still out of memory.
        }
    }

    有什么方式可以改善上面的情况呢?

    答:lifetime Scopes

    // var container = …
    while (true)
    {
        using (var lifetimeScope = container.BeginLifetimeScope())
        {
            var r = lifetimeScope.Resolve<IMyResource>();
            // r, all of its dependencies and any other components
            // created indirectly will be released here
        }
    }

    Lifetime Scopes 可以被嵌套使用:

    var ls1 = container.BeginLifetimeScope();
    var ls2 = ls1.BeginLifetimeScope();
    // ls1 is a child of the container, ls2 is a child of ls1

    Lifetime Scopes 不会产生上下文依赖:

    var ls1 = container.BeginLifetimeScope();
    var ls2 = container.BeginLifetimeScope();
    // ls1 and ls2 are completely independent of each other

    Owned Instance:

    Owned instances (Owned<T>) are the last tale in Autofac’s lifetime story.

    An owned instance is a component that comes wrapped in its own lifetime scope. This makes it easier to keep track of how a component should be released, especially if it is used outside of a using statement.

    To get an 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 IMyService from that. The only difference is that the IMyService and the lifetime scope that holds it come wrapped up together in a single object.

    The service implementation is available through the Value property:

    // Value is IMyService
    ownedService.Value.DoSomething();

    When the owned instance is no longer needed, it and all of its disposable dependencies can be released by disposing the Owned<T> object:

    ownedService.Dispose();

    Owner Instance 与 Fun 结合使用:

    Components that are returned from Func<T> delegates are associated with the same lifetime scope as the delegate itself. If that component is itself contained in a lifetime scope, and it creates a finite number of instances through the delegate, then there’s no problem – everything will be cleaned up when the scope completes.

      If the component calling the delegate is a long-lived one, then the instances returned from the delegate will need to be cleaned up eagerly. To do this, Owned<T> can be used as the return value of a factory delegate

    class MyComponent2 : IMyService2
    {
        Func<Owned<IMyResource>> _resourceFactory;
    
        public MyComponent(Func<Owned<IMyResource>> resourceFactory)
        {
            _resourceFactory = resourceFactory;
        }
    
        public void Go()
        {
            while (true)
                using (var r = _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 dependency on ILifetimeScope

    参考文章:

    http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/

    http://nblumhardt.com/2010/01/the-relationship-zoo/

  • 相关阅读:
    catalina_home与catalina_base
    log4j配置
    lsof
    定时任务-crontab
    access日志配置
    java常识
    mysql事务隔离级别与实现原理
    文件描述符设置
    gpio 預設值
    synchronous interrupt and asynchronous interrupt
  • 原文地址:https://www.cnblogs.com/liaofeng/p/Autofac.html
Copyright © 2011-2022 走看看