如何正确处理对象:注入与拥有
本文关键字:注入 拥有 对象 正确处理 | 更新日期: 2023-09-27 18:20:22
我有一个关于处理对象的问题。
考虑这个IDisposable
类
public class MyClass : DisposableParentClass
{
private MyProp _prop;
public MyClass(MyProp prop)
{
_prop = prop;
}
public MyClass()
{
_prop = new MyProp();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_prop.Dispose();
}
base.Dispose(disposing);
}
}
在第一个构造函数上,MyProp
被注入。因此MyClass
不是对象的所有者。但是在第二个构造函数上,MyProp
是在本地创建的。我应该始终处理MyProp
,还是应该先检查它是否已注入。
public class MyClass : DisposableParentClass
{
private MyProp _prop;
private bool _myPropInjected = false;
public MyClass(MyProp prop)
{
_prop = prop;
_myPropInjected = true;
}
public MyClass()
{
_prop = new MyProp();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!_myPropInjected) { _prop.Dispose(); }
}
base.Dispose(disposing);
}
}
如果您的类应该处理以下两种情况:
- 它不是所提供对象的所有者,不应该处理它
- 它是创建的对象的所有者,应该处理它
那么,是的,你需要有一个机制来告诉这两种情况。
一个常见的方法(对我来说很常见)是使用这样的命名约定:
private MyProp _prop;
private bool _ownsProp = false;
即。颠倒你的标志的含义,但这是细节,你的解决方案很好,是的,你需要这样的解决方案。
如果你有很多这样的字段,每个字段都必须有自己的bool字段来处理这个问题,那么创建一个辅助类可能是值得的,比如这个LINQPad程序演示的:
void Main()
{
Injectable i1 = new Injectable();
Injectable i2 = new Injectable(new Injected("A"));
Injectable i3 = new Injectable(new Injected("A"), new Injected("B"));
Debug.WriteLine("dispose a and b");
i1.Dispose();
Debug.WriteLine("dispose b");
i2.Dispose();
Debug.WriteLine("no dispose");
i3.Dispose();
}
public class Injected : IDisposable
{
public Injected(string name) { Name = name; }
public string Name { get; set; }
public void Dispose() { Debug.WriteLine(Name + " disposed"); }
}
public class Injectable : IDisposable
{
private Ownable<Injected> _A;
private Ownable<Injected> _B;
public Injectable(Injected a, Injected b)
{
_A = Ownable.NotOwned(a);
_B = Ownable.NotOwned(b);
}
public Injectable(Injected a)
{
_A = Ownable.NotOwned(a);
_B = Ownable.Owned(new Injected("B"));
}
public Injectable()
{
_A = Ownable.Owned(new Injected("A"));
_B = Ownable.Owned(new Injected("B"));
}
public void Dispose()
{
_A.Dispose();
_B.Dispose();
}
}
public class Ownable<T> : IDisposable
where T : class
{
private readonly T _Instance;
private readonly Action _CleanupAction;
public Ownable(T instance, bool isOwned)
{
_Instance = instance;
if (isOwned)
{
IDisposable disposable = instance as IDisposable;
if (disposable == null)
throw new NotSupportedException("Unable to clean up owned object, does not implement IDisposable");
_CleanupAction = () => disposable.Dispose();
}
}
public Ownable(T instance, Action cleanupAction)
{
_Instance = instance;
_CleanupAction = cleanupAction;
}
public T Instance { get { return _Instance; } }
public void Dispose()
{
if (_CleanupAction != null)
_CleanupAction();
}
}
public static class Ownable
{
public static Ownable<T> Owned<T>(T instance)
where T : class
{
return new Ownable<T>(instance, true);
}
public static Ownable<T> Owned<T>(T instance, Action cleanupAction)
where T : class
{
return new Ownable<T>(instance, cleanupAction);
}
public static Ownable<T> NotOwned<T>(T instance)
where T : class
{
return new Ownable<T>(instance, false);
}
}
这里也可以做不同的注释。
这取决于你的MyClass
实际上在做什么。
例如,如果我们谈论的是一个类,它从设备中读取视频流,然后对其应用一些过滤器,并将数据写入用户指定的文件,其中文件写入是通过从外部传递的流进行的,比如这样:
public class VideoProcessor : IDisposable {
private FileStream _videoFile = null;
private VideoProcessor() {}
//user specified FileStream
public VideoProcessor(FileStream fs) {_videoFile = fs;}
public void Dispose() {
_videoFile.Dispose(); //Dispose user passed FileStream
}
}
在dispose调用期间处理传递的流对象,实际上会产生sence。
在其他情况下,是的,如果您不是对象的所有者,最好不要销毁该对象。让调用者来决定何时是销毁对象的合适时机。