接口上的实现特定方法 - 如何避免它们?

时间:2009-12-22 15:43:44

标签: .net interface idisposable

  • 我们有一个使用IoC容器传递给构造函数的接口
  • 我们有多个实现此接口的类。

问题是,需要清理一些(并非所有)实现,最好使用IDisposable接口。

由于并非所有实现都需要“Dispose”方法,所以我是否还要包含它(我意识到我实际上并没有实现IDisposable,这只是一个例子)?对我来说,似乎知道接口实际实现的类应该知道如何清理这些对象。但是,这是IoC容器,我没有看到任何优雅的方式来通知它在它创建的特定类上调用清理。

interface IBar
{
  void DoWork();
  void Dispose(); //Not all implementations need this
}

class Foo : IBar
{
  public void DoWork()
  {
    //implementation 1
  }

  public void Dispose()
  {
    //cleanup, which needs to be called
  }
}

class Foo2 : IBar
{
  public void DoWork()
  {
    //implementation 2
  }

  public void Dispose()
  {
    //No cleanup needed in this implementation
  }
}

4 个答案:

答案 0 :(得分:3)

您可以在需要它的人身上实现IDisposable然后执行此操作:

interface IBar
{
    void Bar();
}

class Foo : IBar
{
    public void Bar() { }
}

class Foo2 : IBar, IDisposable
{
    public void Bar() {}
    public void Dispose() {}
}

class Program
{
    static void Main(string[] args)
    {
        foreach (IBar bar in new IBar[] { new Foo(), new Foo2() })
        {
            bar.Bar();

            IDisposable disp = bar as IDisposable;

            if (disp != null)
            {
                disp.Dispose();
            }
        }
    }
}

答案 1 :(得分:1)

以下是什么问题?

interface IBar { void DoWork(); }
class Foo : IBar, IDisposable { // details, implements Dispose }
class Foo2 : IBar { // details, no Dispose }

答案 2 :(得分:1)

奇怪的问题。如果您的关注点是IDisposable,那么大多数容器都会检查实现,如果它包含IDisposable的实现,则容器会在释放实例时自动调用Dispose ()

所以,

// pure clean business interface. no dispose member
public interface ISomeBusinessInterface { }

// an implementation that does not require any 'disposing'
// and implements *only* business interface
public class SomeBusinessImplementation : 
    ISomeBusinessInterface
{
}

// an implementation that contains heavy resources and 
// requires 'disposing'
public class SomeDisposableBusinessImplementation : 
    ISomeBusinessInterface,
    IDisposable
{
}

// a typical consumer. no knowledge of instance life-cycle
public class SomeConsumer 
{
    // injector constructor
    public SomeConsumer (ISomeBusinessInterface business) { }
}

您的消费者应该不了解注入组件的生命周期,并且不以任何形式或形式对其负责。从这个角度来看,ISomeBusinessInterface没有继承或暴露任何这样的Dispose方法是有意义的 - 我的意思是,考虑一下你是否处理了一个重要的单例服务!那会有多么令人尴尬?

那么谁负责注入组件的生命周期?好吧,容器当然是!如前所述,大多数容器将检查组件实现以查找IDisposable的实现[也是使用标准CLR定义的接口的另一个原因],并在确定组件已达到其结束时调用Dispose生活。所以SomeDisposableBusinessImplementation最终会被妥善处理掉。 :)


Castle Windsor

Castle Windsor IoC容器跟踪并维护对其创建的所有实例的引用。它使用反射来确定实例是否为“一次性”,然后在实例的生命周期完成时调用Dispose ()。对于长寿命物体,这是在处置容器时。对于瞬态短期对象,这是消费者*。{/ p>显式调用Release (object)的时间

* =这提出了一个重点,瞬态对象应该通过显式调用Resolve<T> ()获取,并通过显式调用Release (object)释放。隐式注入瞬态类可能会导致内存泄漏!


<强> StructureMap

StructureMap IoC container does not track and maintain references to transient instances.这几乎意味着对象生命周期管理有点复杂+。这对于短暂的短期对象非常有用,因为不需要额外的簿记except the usual。但是,对于长寿命对象,您必须extend the framework, reflect, and dispose of instances yourself

+ =复杂的imo。

答案 3 :(得分:0)

什么时候需要调用Dispose?执行工作或应用程序关闭后?如果是后者,你的IoC容器不支持这样的清理吗?在Java和Spring IoC容器中,您的实现将实现Spring的一次性接口,容器将在关闭期间调用dispose方法。