2013-09-25 34 views
0

我发现自己做这在我的课数据库对象:通用处置和C#设置为null

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

的几个问题...

  1. 我是不是应该设计数据库对象有一个更短的生命,所以 能够把它放在using块?
  2. 有没有一种通用的方法来做到这一点,而不是每次我处理一些东西时写3条线 ?

那些东西放在一边,我感兴趣的类似于这样是否可行:

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

就像你提到的,如果对象实现IDisposible,您可以使用使用。对于数据库的东西,我会建议你使用using语句。 – Justin

+0

是什么让你避免使用使用块? – Shawn

+1

此代码是否在包含类的Dispose()方法中?如果是这样,这个问题是问同样的事情:[处置实现IDisposable的成员](http:// stackoverflow。COM /问题/ 3022650 /配置 - 的成员 - 即 - 实施 - IDisposable接口)。它有一个非常好的解决方案。另外,如果这是在'Dispose()'方法中,则不需要设置'Db = null;'它没有任何好处。 –

回答

0
  1. 大抵如此。如果没有看到更多的课程,就无法确定。但作为一个经验法则,我尽量避免使用可丢弃的字段或属性(我假设它是如此,因为如果它是局部变量,则可以使用using)。管理它们太难了,除非你的课程也是IDisposable,并且你用Dispose()方法清理它。
  2. 您可以将这些行重构为他们自己的方法,例如, DisposeDb()
0
public static void MyDispose(ref DbContext db) 
    { 
     if (db != null) 
     { 
      db.Dispose(); 
      db = null; 
     } 
    } 

或类似的东西卡在某处类。

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); 
    } 
}