1

我发现自己为班级中的数据库对象执行此操作:

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

几个问题 ...

  1. 我是否应该将 Db 对象设计为具有更短的寿命,从而能够将它放在一个using块中?
  2. 有没有一种通用的方法来做到这一点,而不是每次我处理一些东西时都写 3 行?

撇开这些不谈,我对是否有可能发生类似的事情感兴趣:

static void SafeDispose(ref IDisposable obj)
{
    if (obj != null)
    {
        obj.Dispose();
        obj = null;
    }
}
4

3 回答 3

0
  1. 大概是这样。如果没有看到更多的课程,就不可能肯定地说。但根据经验,我尽量避免使用一次性的字段或属性(我假设就是这样,因为如果它是局部变量,你可以使用using)。管理它们太难了,除非你的类也是,并且你在你的方法IDisposable中清理它。Dispose()
  2. 您可以将这些行重构为它们自己的方法,例如DisposeDb().
于 2013-09-25T16:27:06.893 回答
0
    public static void MyDispose(ref DbContext db)
    {
        if (db != null)
        {
            db.Dispose();
            db = null;
        }
    }

或类似的东西卡在某个班级的某个地方。

于 2013-09-25T16:28:34.050 回答
0
  1. 有没有一种通用的方法来做到这一点,而不是每次我处理一些东西时都写 3 行?

要以可重用的方式实现类似的功能,您可以创建一个静态辅助方法:

public static class Disposable
{
    public static void Dispose(ref IDisposable obj)
    {
        if (obj!= null)
        {
            obj.Dispose();
            obj = null;
        }
    }
}

您可以像这样调用该方法:

Disposable.Dispose(ref someDisposableObject);

这不适用于属性,因为您不能将属性传递给ref参数。要使其也适用于属性,您可以使用表达式:

public static class Disposable
{
    public static void Dispose(Expression<Func<IDisposable>> expression)
    {
        var obj = expression.Compile().Invoke();
        if (obj == null)
            return;

        obj.Dispose();

        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null || !IsMemberWritable(memberExpression.Member))
            return;

        var nullExpression = Expression.Constant(null, memberExpression.Type);
        var assignExpression = Expression.Assign(memberExpression, nullExpression);
        var lambdaExpression = Expression.Lambda<Action>(assignExpression);

        var action = lambdaExpression.Compile();
        action.Invoke();
    }

    private static bool IsMemberWritable(MemberInfo memberInfo)
    {
        var fieldInfo = memberInfo as FieldInfo;
        if (fieldInfo != null)
            return !fieldInfo.IsInitOnly && !fieldInfo.IsLiteral;

        var propertyInfo = memberInfo as PropertyInfo;
        if (propertyInfo != null)
            return propertyInfo.CanWrite;

        return true;
    }
}

此方法适用于变量、字段和属性。它处理任何一次性对象,但仅在可写时将其设置为 null。

您可以使用相同的方式处理任何内容,Foo.CleanUp如下例中的方法所示:

public class Bar : IDisposable
{
    // ...
}

public class Foo
{
    private Bar _barField = new Bar();

    public Bar BarProperty { get; set; } = new Bar();

    public void CleanUp()
    {
        Disposable.Dispose(() => _barField);
        Disposable.Dispose(() => BarProperty);

        var barVariable = new Bar();
        Disposable.Dispose(() => barVariable);
    }
}
于 2017-05-13T09:20:34.743 回答