8

DI/IoC 컨테이너 OpenNETCF.IoC에서 작업 중이며 컨테이너 컬렉션의 IDisposable 항목에 대한 라이프 사이클 관리 양식을 추가하는 (합리적인) 기능 요청이 있습니다.DI : IDisposable 개체의 수명 처리

내 현재의 생각은 객체가 삭제되었는지 확인하기 위해 객체를 질의 할 수 없으며 객체가 삭제되었을 때 이벤트를 얻을 수 없기 때문에 객체에 대한 래퍼 형식을 만들어야한다는 것이다. 개발자는 프레임 워크가 관리되기를 원합니다. 잘

public TTypeToBuild AddNew<TTypeToBuild>() { ... } 

내가 새로운 방법을 추가 고려 중이 야 (: 지금 AddNew (단순 위해 우리는 하나의 과부하 거기에 더 추가가없는 가정합니다)에 추가 할 수있는 객체

그 중 그룹,하지만 당신은) 사진을 찍어 :

public class DisposableWrappedObject<T> 
    where T : class, IDisposable 
{ 
    public bool Disposed { get; private set; } 
    public T Instance { get; private set; } 

    internal event EventHandler<GenericEventArgs<IDisposable>> Disposing; 

    internal DisposableWrappedObject(T disposableObject) 
    { 
     if (disposableObject == null) throw new ArgumentNullException(); 

     Instance = disposableObject; 
    } 

    ~DisposableWrappedObject() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     lock(this) 
     { 
      if(Disposed) return; 

      EventHandler<GenericEventArgs<IDisposable>> handler = Disposing; 
      if(handler != null) 
      { 
       Disposing(this, new GenericEventArgs<IDisposable>(Instance)); 
      } 

      Instance.Dispose(); 

      Disposed = true; 
     } 
    } 
} 
다음 DisposableWrappedObject은 다음과 같습니다

public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>() 
    where TTypeToBuild : class, IDisposable 
{ 
    ... 
} 

이제 항목이 AddNewDIsposable을 통해 컨테이너에 추가되면 이벤트 핸들러가 추가되어 래퍼를 통해 Disposed 될 때 프레임 워크가 기본 컬렉션에서 제거하도록합니다.

실제로 이것을 구현했으며 단위 테스트를 통과했습니다. 그러나 이것이 어디에서 고장 났는지, 소비하는 개발자에게 어떻게 더 친숙해질 수 있는지에 대한 의견을 찾고 있습니다.

private object AddNew(Type typeToBuild, string id, bool wrapDisposables) 
{ 
    .... 

    object instance = ObjectFactory.CreateObject(typeToBuild, m_root); 

    if ((wrapDisposables) && (instance is IDisposable)) 
    { 
     DisposableWrappedObject<IDisposable> dispInstance = new 
       DisposableWrappedObject<IDisposable>(instance as IDisposable); 
     dispInstance.Disposing += new 
       EventHandler<GenericEventArgs<IDisposable>>(DisposableItemHandler); 
     Add(dispInstance as TItem, id, expectNullId); 
     instance = dispInstance; 
    } 

    .... 

    return instance; 
} 

private void DisposableItemHandler(object sender, GenericEventArgs<IDisposable> e) 
{ 
    var key = m_items.FirstOrDefault(i => i.Value == sender).Key; 
    if(key == null) return; 
    m_items.Remove(key); 
} 
+0

우리는 추가되는 특정 기능의 풀러 설명을받을 수 있습니까? 사람들이 필요로하는 유스 케이스는 무엇입니까 (IoC 프레임 워크) 또는 최종 사용자로서의 이벤트 처리기입니까? 기타 ... – Quibblesome

+0

유스 케이스는 자동화 된 라이프 사이클 관리를 추가하는 것입니다. IDisposable 항목을 컬렉션에 추가하고 나중에 Dispose를 호출하면 컨테이너가 개체의 루트를 보유하기 때문에 실제로 정리되지 않습니다. 그 아이디어는 콜렉션으로 돌아가서 찾을 필요없이 객체에서 Dispose를 호출 할 수 있으며, 자동으로 컬렉션을 제거하게 할 수 있다는 것입니다. 이벤트는 프레임 워크에 의해 순수하게 내부적으로 사용되며 (심지어 외부에서 사용되지 않도록 내부로 표시되기도 함) 처리기가 컬렉션에서이를 제거합니다. – ctacke

+0

명확성을 위해 이벤트 처리를 추가하는 질문을 업데이트했습니다. – ctacke

답변

3

가 어쩌면 내가 모르는 뭔가가있어,하지만 :

가 EDIT 1 폐기 이벤트를 사용하는 방법에 대한 질문이 있었다 때문에

는, 여기에 몇 가지 코드입니다 (중요 무엇을 손질) API에 새로운 메소드를 추가하는 이유는 무엇입니까? 개체가 컨테이너에 추가되면 IDisposable인지 여부를 확인하고 적절한 경우 개체를 처리 할 수 ​​있습니다.

소멸자가 필요한지 궁금합니다. 컨테이너가 IDisposable (Unity의 것 같음)이라고 가정하면 Basic Dispose Pattern을 구현하고 많은 GC 오버 헤드를 절약 할 수 있습니다.

적용 할 수 몇 가지 질문

는 :

+0

아,하지만 캐스팅을 한 상태라면 뭐야? IDisposable이고 컨테이너에 넣어야한다는 것을 알고 있지만 AddNew <> 메서드가 입력 유형을 반환해야하므로 컨테이너를 반환 할 수 없습니다. API가 원할 때 객체를 직접 반환하면 객체는 래핑 된 것을 알지 못하고 컨테이너가 아닌 인스턴스에서 Dispose를 호출합니다. 다시 한번 GC'ed되지 않는 Disposed 객체를 보유하는 문제가 있습니다. – ctacke

+5

@ctacke : 소비자가 IoC로 게임 할 때 준수해야하는 몇 가지 규칙이 있습니다 : * DI 컨테이너에 * 생성 * 객체의 책임을 넘겨 줄 경우, 인스턴스의 * destroy *를 포함하여 * 모든 * 평생 관리를 전달해야합니다 . 따라서 주입 된 종속성을 조기에 처분하면 소비자의 측면에서 오류가 발생할 수 있습니다. 이는 해당 인스턴스가 여러 소비자간에 공유 될 수 있기 때문입니다. 나는 당신이 API를 과도하게 복잡하게 사용하여 단순히 사용법을 잘못 이해할 필요가 있다고 생각하지 않는다. –