문제

현재 AutoFac 사용 방법을 배우고 있으며 처분에 집착하고 있습니다. IDisposable 객체는 결정적으로. 내 문제를 언급하기 전에 먼저 상황을 제시하겠습니다.

시작 위치 :

내 객체 모델이 다음 인터페이스를 통해 정의되었다고 가정 해 봅시다.

interface IApple : IDisposable
{
    void Consume();
}

interface IHorse
{
    void Eat(IApple apple);   // is supposed to call apple.Consume()
}

interface IHorseKeeper
{
    void FeedHorse();   // is supposed to call horse.Eat(apple)
                        //   where 'horse' is injected into IHorseKeeper
                        //   and 'apple' is generated by IHorseKeeper on-the-fly
}

또한, 나는 IApple 공장:

delegate IApple AppleFactory;

자동 구성 구성 :

이제 위의 유형을 다음과 같이 등록하겠습니다. 두 클래스의 코드를 생략하고 있습니다. Apple 그리고 Horse, 그들은 구현하기가 사소하기 때문에 :

var builder = new Autofac.ContainerBuilder();

builder.RegisterType<Apple>().As<IApple>();
builder.RegisterType<Horse>().As<IHorse>();
builder.RegisterType<HorseKeeper>().As<IHorseKeeper>();
builder.RegisterGeneratedFactory<AppleFactory>();

내 문제:

방법을 구현하는 방법을 잘 모르겠습니다 IHorseKeeper.Feed. 내가 현재 가지고있는 것은 다음과 같습니다.

class HorseKeeper : IHorseKeeper
{
    private readonly IHorse horse;
    private readonly AppleFactory appleFactory;

    public HorseKeeper(IHorse horse, AppleFactory appleFactory)
    //                 ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^
    //                         constructor injection
    {
        this.horse = horse;
        this.appleFactory = appleFactory;
    }

    public void FeedHorse()
    {
        using (var apple = appleFactory())
        {
            horse.Eat(apple);
        }  // <- Dispose() apple now (ASAP), as it's no longer needed!
    }
}

이것은 완전히 자동 금속성이기 때문에 내가 원하는 코드입니다. 그것은 다른 IOC 컨테이너와 함께 작동 할 수 있습니다. AppleFactory 예상대로 작동합니다.

그러나 AutoFac은 다음을 처리하기 때문입니다 AppleFactory 나를 위해, 그것은 모든 것을 추적 할 것입니다 IApple 그것이 나를 위해 생산하는 대상이므로 Dispose 컨테이너의 수명이 끝날 때 자체. 즉, 생산 된 apple 두 번 배치됩니다.

등록한다고 생각합니다 IApple ~처럼 .ExternallyOwned() AutoFac이 더 쉽게 처리 할 수있는 경우가있을 수 있으므로 실행 가능한 솔루션이 아닙니다. IAppleS '수명.

AutoFac을 사용한 결정 론적 처분 중첩 컨테이너를 사용해야합니다 container.BeginLifetimeScope(), 그러나 나는 이것을 안에 사용하고 싶지 않습니다 HorseKeeper.FeedHorse 그렇다면 HorseKeeper AutoFac에 의존하게되며 코드를 IOC-Agnostic으로 유지하고 싶습니다.

의문:

어떻게 구현합니까? HorseKeeper.FeedHorse IOC (Autofac)-공연 방식에서 온도에서 생성 된 객체가 제대로 배치되도록 보장하는 동시에?

도움이 되었습니까?

해결책

여기서 다른 답변은 통찰력이 있지만 문제가 있습니다. 두 경우 모두 Apple에 처분이 필요한 다른 종속성이있는 경우 올바른 정리는 발생하지 않습니다.

AutoFac 2는 "소유 인스턴스"라는 새로운 기능을 제공합니다. 등록 코드가 AutoFac 1.4라는 것을 알았으므로 업그레이드 할 수 없다면 알려주십시오 (이를 수행 할 수있는 다른 투명한 방법이 있습니다.)

평소와 같이 Apple을 등록하십시오 (외부 소유가 아님) :

builder.RegisterType<Apple>().As<IApple>();

AppleFactory를 다음과 같이 선언합니다.

public delegate Owned<IApple> AppleFactory();

AutoFac 2에서는 더 이상 RegisterGeneratedFactory ()를 호출 할 필요가 없습니다. 이것은 자동입니다.

그런 다음 말키퍼에서 다음과 같은 말을 먹이십시오.

public void FeedHorse()
{
    using (var apple = appleFactory())
    {
        horse.Eat(apple.Value);
    }
}

(기본 IAPPLE을 얻으려면 .Value 속성에 유의하십시오.

사용 블록이 끝나면 Apple과 모든 종속성이 정리됩니다.

IAPPLE을 직접 사용하는 다른 구성 요소 (종속성으로) 일반적인 동작이됩니다.

다른 팁

유일한 방법은 Apple 등록을 ExternallyOwned 수정 자. 이것은 Autofac에게 처분을 위해 객체를 추적하지 말고 외부 (코드)가 처분을 처리하도록하도록 지시합니다. 그러나 당신이 말한 것처럼, 당신은 이제 Autofac에서 자동 도움을받지 않기 때문에 모든 사과가 수동으로 배치되어 있는지 확인해야합니다.

builder.RegisterType<Apple>().As<IApple>().ExternallyOwned();

이 등록을 통해 피드 코드는 예상대로 작동합니다.

메모: 토론에서 인터페이스가 상속되어야하는지 여부 IDisposable 또는 그렇지 않음 : 인터페이스가 상속 될 때 IMO IDisposable, 이것은 "소비"개발자에게 인스턴스가 어느 시점에 배치되어야한다는 표시입니다. iApple의 경우, 해당 인터페이스도 idisposable이므로 개발자는 인스턴스를 처리해야합니다 (및 ~ 해야 하다 또한 외부 소유로 등록됩니다). 반면에, Apple 클래스가 다음과 같이 보였다면.

class Apple: IApple, IDisposable
{ }

IAPPLE 소비자는 이제 인스턴스가 idisposable이라는 사실을 완전히 알지 못합니다. 이 경우 컨테이너가 처리를 처리하도록합니다.

그래서 제 결론은 Apple과 Iapple의 개발자가 소비자가 처리를 처리하거나 용기에 맡기도록 요구하는지 여부를 선택하는 것이 저에게 달려 있다는 것입니다.

때때로 Apple 인스턴스의 수명을 직접 관리하고 때로는 컨테이너가 처리하려면 두 인터페이스를 정의 할 수 있습니다.

public IApple
{
   void Consume();
}

public IDisposableApple : IApple, IDisposable
{
}

그런 다음 수업을 두 번 등록하십시오.

builder.RegisterType<Apple>().As<IApple>();
builder.RegisterType<Apple>().As<IDisosableApple>().ExternallyOwned(); 

그런 다음 사과를 만들고 처분 해야하는 클래스에 처분 할 수있는 사람을 주입 할 수 있습니다.

컨테이너와 동일한 수명을 가진 사과가 필요한 클래스의 경우 대신 IAPPLE을 주입합니다.

그러나 두 가지가 필요하다는 사실은 당신이 믹스를하고 있음을 나타낼 수 있습니다. 새로운 및 주사제. Apple은 단순히 "새로운"개체 일 수 있습니다. 즉 IOC 컨테이너에서 관리 할 필요가없는 개체입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top