LightInject: внедрение конструктора и IDisposable

Я хотел бы использовать функцию внедрения конструктора LightInject, но сначала я хотел бы прояснить ситуацию с управлением жизненным циклом IDisposables.

Рассмотрим следующее:

Пример А

public class Foo : IDisposable
{
    readonly IBar bar;
    public Foo(IBar bar)
    {
        this.bar = bar;
    }

    public void Dispose()
    {

    }
}

Пример Б

 public class Foo : IDisposable
 {
    readonly IBar bar;
    public Foo(Func<string, IBar> bar)
    {
        this.bar = bar("myParameter");
    }

    public void Dispose()
    {

    }
 }

Мои вопросы для обоих примеров:

  1. Будет ли метод Dispose вызываться LightInject на IBar после того, как Foo будет удален, или я должен вызывать метод dispose самостоятельно?
  2. Если IBar использует PerContainerLifeTime, будет ли Dispose вызываться после удаления каждого экземпляра Foo?

Редактировать Что ж, второй вопрос глуп, я понимаю, экземпляр PerContainerLifeTime, конечно, удаляется, когда контейнер удаляется. Мой общий вопрос будет заключаться в том, отслеживает ли LightInject введенные зависимости и удаляет ли их сам?


person uzul    schedule 01.04.2015    source источник


Ответы (1)


LightInject будет отслеживать экземпляры, которые он создает, только если служба/зависимость зарегистрирована с помощью PerScopeLifetime или PerRequestLifetime. Взгляните на следующий пример:

class Program
{
    private static IServiceContainer container = new ServiceContainer();

    static void Main(string[] args)
    {
        container.Register(f => new Foo("PerScopeFoo"), "PerScopeFoo", new PerScopeLifetime());
        container.Register(f => new Foo("PerRequestFoo"), "PerRequestFoo", new PerRequestLifeTime());
        container.Register(f => new Foo("PerContainerFoo"), "PerContainerFoo", new PerScopeLifetime());
        container.Register(f => new Foo("TransientFoo"), "TransientFoo");

        using (container.BeginScope())
        {
            var first = container.GetInstance<Foo>("PerScopeFoo");
            var second = container.GetInstance<Foo>("PerScopeFoo");
            Debug.Assert(first == second);

            first = container.GetInstance<Foo>("PerRequestFoo");
            second = container.GetInstance<Foo>("PerRequestFoo");

            Debug.Assert(first != second);

            first = container.GetInstance<Foo>("PerContainerFoo");
            second = container.GetInstance<Foo>("PerContainerFoo");

            Debug.Assert(first == second);

            first = container.GetInstance<Foo>("TransientFoo");
            second = container.GetInstance<Foo>("TransientFoo");

            Debug.Assert(first != second);
        }

        container.Dispose();

        Console.ReadKey();
    }        
}

public class Foo : IDisposable
{
    private readonly string name;

    public Foo(string name)
    {
        this.name = name;
    }

    public void Dispose()
    {
        Console.WriteLine(name + " disposed");
    }
}
person seesharper    schedule 04.04.2015
comment
Спасибо за ваш ответ :) Итак, означает ли это, что экземпляр PerScope удаляется, когда область удаляется, и что экземпляр PerRequest удаляется, когда на него больше не ссылаются? (внутренне с помощью WeakReference?) - person uzul; 04.04.2015
comment
Нет, это означает, что экземпляр PerRequest удаляется, когда область действия заканчивается или когда область действия устанавливается, чтобы быть точным :) - person seesharper; 07.04.2015
comment
если я не использую области видимости, будет ли это означать утечку памяти при использовании PerRequest? если это так, мне придется использовать области. (особенно асинхронная версия). Также я почувствовал потребность в CacheLifeTime, который возвращает один и тот же экземпляр до истечения времени ожидания. Есть ли что-нибудь, реализующее что-то подобное? - person uzul; 10.04.2015
comment
Как правило, вы всегда должны убедиться, что объекты, реализующие IDisposable, удаляются явно. Сам факт того, что они реализуют IDisposable, обычно указывает на то, что они удерживают ресурсы, которые должны быть освобождены явным образом. LightInject управляет удалением таких объектов с помощью областей видимости. Что касается CacheLifetime, вы можете реализовать интерфейс ILifetime и, таким образом, создать любое время жизни, какое захотите. - person seesharper; 13.04.2015
comment
@seesharper подключит LightInject.Mvc к конвейеру Mvc и автоматически создаст область в начале http-запроса и удалит область в конце http-запроса? - person Chris Marisic; 13.04.2015
comment
В контексте веб-приложения область действия начинается, когда начинается веб-запрос, и заканчивается, когда заканчивается веб-запрос. - person seesharper; 14.04.2015
comment
Кажется, существует ошибка, связанная с тем, что зарегистрированные объекты PerScopeLifetime не удаляются, если что-то не содержит ссылку на них. - person Michael Brown; 05.05.2020