Implementing Dispose() with class derived from System.ComponentModel.Component - c#

I made a class that derives from Component:
public class MyComponent: System.ComponentModel.Component
{
}
I saw that Visual Studio put this code in for me:
protected override void Dispose(bool disposing)
{
try
{
if (disposing && (components != null))
{
components.Dispose();
}
}
catch
{
throw;
}
finally
{
base.Dispose(disposing);
}
}
MyComponent has a member that is a DataSet and maybe there's some other members that implement IDisposable. What, if anything, do i need to modify with the Dispose() method to make sure things are cleaned up properly? Thanks for helping.

Change:
if (disposing && (components != null))
{
components.Dispose();
}
to be:
if (disposing && (components != null))
{
_dataset.Dispose();
components.Dispose();
}

Check any disposable member objects and dispose them if they are not null.

I came up with this class:
public class DisposableComponentWrapper : IComponent
{
private IDisposable disposable;
public DisposableComponentWrapper(IDisposable disposable)
{
this.disposable = disposable;
}
public DisposableComponentWrapper(IDisposable disposable, ISite site)
: this(disposable)
{
Site = site;
}
public void Dispose()
{
if (disposable != null)
{
disposable.Dispose();
}
if (Disposed != null)
{
Disposed(this, EventArgs.Empty);
}
}
public ISite Site { get; set; }
public event EventHandler Disposed;
}
and extension method to IContainer:
public static void Add(this IContainer container, IDisposable disposableComponent)
{
var component = (disposableComponent as IComponent);
if(component == null)
{
component = new DisposableComponentWrapper(disposableComponent);
}
container.Add(component);
}
Which might help those willing to enlist disposable resources to their forms.
Note: I'm not certain of the behaviour for IComponent.Disposed, MSDN doesn't say much about how it should be called in implementation of this interface, the documentation sounds like talking about client code registering to the event more than when it should be triggered by implementations of this interface.

Wrap the disposables in components and add them in the components collection. The generated implementation of the dispose pattern will dispose of them correctly.
public partial class MyComponent : System.ComponentModel.Component
{
private readonly System.Data.DataSet _dataSet;
public MyComponent(System.Data.DataSet dataSet)
{
_dataSet = dataSet ?? throw new System.ArgumentNullException(nameof(dataSet));
components.Add(new DisposableWrapperComponent(dataSet));
}
}
The DisposableWrapperComponent is defined thus:
using System;
using System.ComponentModel;
public class DisposableWrapperComponent : Component
{
private bool disposed;
public IDisposable Disposable { get; }
public DisposableWrapperComponent(IDisposable disposable)
{
Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
}
protected override void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
Disposable.Dispose();
}
base.Dispose(disposing);
disposed = true;
}
}
Inspired by the answer by #smoothdeveloper.
If you need to be able to reset the data set, encapsulating the lifetime management in a property works quite well.
using System;
using System.ComponentModel;
using System.Data;
public partial class MyComponent : Component
{
private const string DataSetComponentName = "dataSet";
public DataSet DataSet
{
get => (DataSet)((DisposableWrapperComponent)components.Components[DataSetComponentName])
?.Disposable;
set
{
var lastWrapper = (DisposableWrapperComponent)components.Components[DataSetComponentName];
if (lastWrapper != null)
{
components.Remove(lastWrapper);
lastWrapper.Dispose();
}
if (value != null)
{
components.Add(new DisposableWrapperComponent(value), DataSetComponentName);
}
}
}
public MyComponent(DataSet dataSet)
{
DataSet = dataSet ?? throw new ArgumentNullException(nameof(dataSet));
}
}
I used this when implementing a Windows Service that creates a disposable object in OnStart and disposes of it in OnStop.

Related

How and where to dispose dbcontext using unity PerRequestLifetimeManager

I am using unity IOC to inject the dbcontext in the relevant classes in a Web API. I am using custom lifetime manager as shown below:
public class PerRequestLifetimeManager : LifetimeManager
{
private readonly object key = new object();
public override object GetValue()
{
if (HttpContext.Current != null &&
HttpContext.Current.Items.Contains(key))
return HttpContext.Current.Items[key];
else
return null;
}
public override void RemoveValue()
{
if (HttpContext.Current != null)
HttpContext.Current.Items.Remove(key);
}
public override void SetValue(object newValue)
{
if (HttpContext.Current != null)
HttpContext.Current.Items[key] = newValue;
}
}
This is injected in global.asax as this:
// context - one context per http request
container.RegisterType(new PerRequestLifetimeManager());
In dbcontext class we have this:
public class BudgetControlDbContext : DbContext, IBudgetControlDbContext
{
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
this._isDisposed = true;
}
public bool IsDisposed
{
get { return this._isDisposed; }
}
}
Question:
Now how to dispose the dbcontext and where that code should be?

Is a ComWrapper class wise to wrap a Interop Com Object

I application that uses a a Interop Com Object. Therefore I had written a wrapper class, to do the freeing in the dispose or if this is not done in the finalizer. So I can use the using keyword, to ensure a freeing is done.
Is using this pattern a good way? Or is there even a class in the Framework that is doing this for me?
class ComWrapper<T> : IDisposable
{
private readonly T comObject;
private bool disposed = false;
public ComWrapper(T comObject)
{
this.comObject = comObject;
}
~ComWrapper()
{
this.Dispose(false);
}
public T ComObject
{
get
{
return this.comObject;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
Marshal.FinalReleaseComObject(this.comObject);
}
}
I personally wouldn't recommend this because it seems somewhat pointless. But, I would recommend having a static class called Utility, with this method:
public static void disposeComObject<T>(ref T comObject)
{
if(Marshal.IsComObject(comObject) && comObject != null)
{
//You need to save the object
if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Workbook))
{
((Microsoft.Office.Interop.Excel.Workbook))comObject.Save();
((Microsoft.Office.Interop.Excel.Workbook))comObject.Close();
}
//You need to save the object
if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Application))
{
((Microsoft.Office.Interop.Excel.Application))comObject.Quit();
}
Marshal.ReleaseComObject(comObject);
comObject = null;
}
}
Now From Code, you can call this like so
...
Microsoft.Office.Interop.Excel comObject = null;
try{
//Open comObject
//Here I would call some functions, and have nested exceptions
}
catch(nestedException err)
{
//Handle at your discretion
}
finally{
Utility.disposeComObject(ref comObject);
}
This is specific to the Excel Namespace, but adjusting it should be easy enough.

How to use IDisposable pattern on Windows Form

I've read about IDisposable pattern on this article and want to implement it in my windows form application. As we know that in windows form .Designer.cs class there is already Dispose method
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
and in .cs class I'm using Typed Dataset to read and save the data.
public partial class frmCustomerList
{
private MyTypedDataSet ds = new MyTypedDataSet();
...
}
So, how to implement IDisposable to dispose MyTypedDataSet? If I implement IDisposable in frmCustomerList and implement its interface
public partial class frmCustomerList : IDisposable
{
private MyTypedDataSet ds = new MyTypedDataSet();
void Dispose()
{
ds.Dispose();
}
}
what about Dispose(bool disposing) method in .Designer.cs?
If you look in the Designer.cs file and look below the dispose method you will see this
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
Only InializeComponent() is warned about not modifing. You can cut (not copy) and paste the protected override void Dispose(bool disposing) out of the designer file and move it in your main code file without worry, just be sure to leave the components.Dispose(); part in as any disposable objects you add through the designer will be put in that collection for disposing.
public partial class frmCustomerList
{
private MyTypedDataSet ds = new MyTypedDataSet();
protected override void Dispose(bool disposing)
{
ds.Dispose();
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
//The rest of your frmCustomerList.cs file.
}
I would dispose any members of the form using one of the forms events such as
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onclosed(v=vs.110).aspx
e.g
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (ds != null)
ds.Dispose();
}
I think you must not care about disposing your class except if you have unmanaged resources. Here is an example where it actually useful:
public class ComplexResourceHolder : IDisposable
{
private IntPtr buffer; // unmanaged memory buffer
private SafeHandle resource; // disposable handle to a resource
public IntPtr Buffer { get { return buffer; } set { buffer = value; } }
public ComplexResourceHolder()
{
this.buffer = ... // allocates memory
this.resource = ... // allocates the resource
}
protected virtual void Dispose(bool disposing)
{
ReleaseBuffer(buffer); // release unmanaged memory
if (disposing)
{
// release other disposable objects
if (resource!= null)
resource.Dispose();
}
}
~ ComplexResourceHolder(){
Dispose(false);
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
}
Check the MSDN for better understanding of Dispose(bool) finalizer override. And this link about unmanaged resources will be useful as well because this is the first reason why you should use IDisposable.
You might wonder to use constructions like below if the class inherits IDisposable:
using (ComplexResourceHolder crh = new ComplexResourceHolder())
{
//Do something with buffer for an instance
//crh.Buffer =
}
Dispose method will be called automatically after closing tag '}'.

Can I reference / use COM objects in my finalizer?

I have a COM type (created using tlbimp.exe) and a C# class that wraps this object. I want to perform some clean up in the finalizer for my C# wrapper. Following the guidelines here I might write something like this:
public class MyClass : IDisposable
{
private IMyComObject comObject;
public MyClass()
{
comObject = new MyComObject();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
// Be tollerant of partially constructed instances
if (comObject != null)
{
comObject.Cleanup();
// Account for object being disposed twice
comObject = null;
}
}
// Other bits go here...
}
I know that finalizers can run in any order and so I should not attempt to use any object that implements a finalizer, however as far as I can tell tlbimp generated COM types don't implement a finalizer and so the above should be OK.
I haven't been able to find any official documentation on this however, so my question is is it safe to reference and use COM objects in a finalizer?
I created a abstract com wrapper class, from which I derive all my com wrapper classes. It works very well. My original code is VB, since I need late binding (this was before C# introduced the dynamic type). The rest of my app is written in c#.
public abstract class ComWrapper : IDisposable
{
protected internal object _comObject;
protected ComWrapper(object comObject)
{
_comObject = comObject;
}
#region " IDisposable Support "
private bool _disposed = false;
protected virtual void FreeManagedObjects()
{
}
protected virtual void FreeUnmanagedObjects()
{
ReleaseComObject(_comObject);
}
private void Dispose(bool disposing)
{
if (!_disposed) {
if (disposing) {
FreeManagedObjects();
}
FreeUnmanagedObjects();
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Finalize()
{
Dispose(false);
base.Finalize();
}
#endregion
}
and
public static class Helpers
{
public static void ReleaseComObject(ref object o)
{
if ((o != null)) {
try {
Marshal.ReleaseComObject(o);
} catch {
} finally {
o = null;
}
}
}
public static string ToDotNetString(object comString)
{
if (comString == null) {
return string.Empty;
}
string s = comString.ToString();
ReleaseComObject(ref comString);
return s;
}
}

ensuring a well-defined object state when a constructor throws an exception

I have a Visual Studio 2008 C# .NET 2.0CF application. I'm using a component base from which two concrete components are derived. The application first attempts to use SomeDisposableComponent. Its constructor throws an exception because it requires a feature that isn't available. Then, the application tries SomeOtherDisposableComponent. Its construction succeeds.
The problem is that the first component's constructor already added itself to the form's container of components before the exception was thrown. So, when the form is disposed the first component's Dispose() member is called even though the object was never fully constructed. That causes problems for the second component's destructor.
How can I ensure that when the first component throws an exception on construction, the references to it are removed?
public abstract class SomeDisposableComponentBase : Component
{
private System.ComponentModel.IContainer components;
private SomeInternalDisposable s_ = new SomeInternalDisposable();
protected SomeDisposableComponentBase()
{
Initializecomponent();
}
protected SomeDisposableComponentBase(IContainer container)
{
container.Add(this);
Initializecomponent();
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
protected abstract void Foo();
#region IDisposable Members
bool disposed_;
protected override void Dispose(bool disposing)
{
// called twice. the first time for the component that failed to initialize properly.
// the second for the one that was used.
if (!disposed_)
{
if (disposing && (components != null))
{
components.Dispose();
}
// on the second call, this throws an exception because it is already disposed.
s_.Close();
disposed_ = true;
}
base.Dispose(disposing);
}
#endregion
}
public SomeDisposableComponent : SomeDisposableComponentBase
{
public SomeDisposableComponent() : base()
{
}
public SomeDisposableComponent(IContainer container) : base(container)
{
// This will throw an exception if it requires a feature that isn't available.
SomeInitFunction();
}
protected override void Foo()
{
// Do something...
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public partial class my_form : Form
{
private SomeDisposableComponentBase d_;
public my_form()
{
InitializeComponent();
if (null == components)
components = new System.ComponentModel.Container();
try
{
// try the default component
d_ = new SomeDisposableComponent(components);
}
catch (System.Exception)
{
try
{
// the default component requires some feature that isn't available. Try a
// backup component.
d_ = new SomeOtherDisposableComponent(components);
}
catch (System.Exception e)
{
// display error to the user if no suitable component can be found.
}
}
}
/// exit button clicked
private void Exit_Click(object sender, EventArgs e)
{
this.Close();
}
/// from the my_form.designer.cs
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
// this function is executed as expected when the form is closed
components.Dispose();
}
base.Dispose(disposing);
}
}
Thanks,
PaulH
Edit: Removed unused code
The container within the SomeDisposableComponentBase was confusing. It's not relevant to the issue and I should have removed it earlier.
public abstract class SomeDisposableComponentBase : Component
{
private SomeInternalDisposable s_ = new SomeInternalDisposable();
protected SomeDisposableComponentBase()
{
}
protected SomeDisposableComponentBase(IContainer container)
{
container.Add(this);
}
protected abstract void Foo();
#region IDisposable Members
bool disposed_;
protected override void Dispose(bool disposing)
{
// called twice. the first time for the component that failed to initialize properly.
// the second for the one that was used.
if (!disposed_)
{
if (disposing)
{
// on the second call, this throws an exception because it is already disposed.
s_.Close();
}
disposed_ = true;
}
base.Dispose(disposing);
}
#endregion
}
public SomeDisposableComponent : SomeDisposableComponentBase
{
public SomeDisposableComponent() : base()
{
}
public SomeDisposableComponent(IContainer container) : base(container)
{
// This will throw an exception if it requires a feature that isn't available.
SomeInitFunction();
}
protected override void Foo()
{
// Do something...
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public partial class my_form : Form
{
private SomeDisposableComponentBase d_;
public my_form()
{
InitializeComponent();
if (null == components)
components = new System.ComponentModel.Container();
try
{
// try the default component
d_ = new SomeDisposableComponent(components);
}
catch (System.Exception)
{
try
{
// the default component requires some feature that isn't available. Try a
// backup component.
d_ = new SomeOtherDisposableComponent(components);
}
catch (System.Exception e)
{
// display error to the user if no suitable component can be found.
}
}
}
/// exit button clicked
private void Exit_Click(object sender, EventArgs e)
{
this.Close();
}
/// from the my_form.designer.cs
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
// this function is executed as expected when the form is closed
components.Dispose();
}
base.Dispose(disposing);
}
}
Your form should be in charge of adding items to its components collection - not the components you're adding to the collection. Doing it inside the added components makes it extremely difficult to reason about what's happening in your form.
// It is not obvious that the component is adding itself to the list
new SomeDisposableComponent(components);
// Instead, be explicit where it matters
Component someDisposableComponent = new SomeDisposableComponent(components);
this.components.Add(someDisposableComponent);
Next, to solve your constructor problem, you should move the logic out of the constructor. This is generally good practice - people do not expect constructors to have side effects, and logic in your constructors makes classes difficult to test. If you want to guarantee that something happens every time you create an instance, create a factory and make it so the factory is the only way to get an instance of your class (make the class' constructor internal, or use some other technique):
public class SomeDisposableComponentFactory {
public SomeDisposableComponent CreateInstance() {
SomeDisposableComponent component = new SomeDisposableComponent();
component.SomeInitFunction();
}
}
Finally, you should consider moving the logic for selecting and creating components out of your form and into a general component factory:
public class ComponentFactory {
// The input parameter can be whatever you need to choose the right component
public Component CreateInstance(object input) {
if (input == something) {
SomeDisposableComponent component = new SomeDisposableComponent();
component.SomeInitFunction();
return component;
}
else {
return new AnotherComponent();
}
}
}
Why does container.Add(this) appear before InitializeComponent()? By definition, you're adding an uninitialized component to the container; that's likely to cause problems even if the initialize method doesn't fail.
Just switch the order:
InitializeComponent();
container.Add(this);
That way, if InitializeComponent throws, the component will never add itself to the container. No need for special cleanup.
I'm not sure why you need that constructor at all, but if for some reason it has to be in the order that you already have (i.e. the InitializeComponent method depends on the container... eek), then put the exception handling in the constructor itself:
try
{
container.Add(this);
InitializeComponent();
}
catch (WhateverException)
{
container.Remove(this);
}
But don't do this unless you really have to; much better to just not add the component to the container until it's fully initialized and stable.

Categories

Resources