Object that calls a method on Dispose - c#

Is there a .NET class which calls a method when it gets disposed, sometimes instead of:
try
{
...
}
finally
{
MyCleanupMethod()
}
I'd like to:
using(new OnDisposed(MyCleanupMethod))
{
...
}
Before I get berated, for three reasons:
For long try blocks it allows the reader to see what needs to be cleaned up at the start
try has an implication that its catching an error (which it's not)
To keep the disposal code private (if the IDisposable object is returned from a class)
Is this valid practice? If so, is a .NET class which does this?

You could add a constructor that takes the action:
public class OnDisposed : IDisposable
{
private readonly Action _disposeAction;
public OnDisposed(Action disposeAction)
{
_disposeAction = disposeAction;
}
public void Dispose()
{
// ...
if(_disposeAction != null)
_disposeAction();
}
}
For example:
using (new OnDisposed(() => Console.WriteLine("Dispose Called")))
{
Console.WriteLine("In using...");
}

Related

Should I dispose DbContext when using Entity Framework Core

I have the following method in the aspx file (.NET Framework 4.6.2 project):
public static string SetAvgPeriodDays(int userId)
{
var service = new AveragePeriodDaysService(EfHelper.GetContext());
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
AveragePeriodDaysService class has a constructor that accepts DbContext instance:
public class AveragePeriodDaysService
{
private readonly MyDbContext _ctx;
public AveragePeriodDaysService(MyDbContext ctx)
{
_ctx = ctx;
}
public string SetAveragePeriodDays(int userId)
{
// main logic goes here...
}
}
And here EfHelper class:
public class EfHelper
{
public static MyDbContext GetContext()
{
var options = new DbContextOptionsBuilder<MyDbContext>();
var connectionString = ...
options.UseSqlServer(connectionString);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
return new MyDbContext(options.Options);
}
}
Question. Should I dispose MyDbContext? If yes, how should I do it properly?
As a rule you should never dispose dependencies that you got from outside because you never know who else uses same instance of this dependency. It means AveragePeriodDaysService can't dispose MyDbContext. But SetAvgPeriodDays knows exactly who will consume MyDbContext because it requested the creation of MyDbContext, hence it can and should dispose it after usage. Use using keyword:
public static string SetAvgPeriodDays(int userId)
{
using(var ctx = EfHelper.GetContext())
{
var service = new AveragePeriodDaysService(ctx);
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
}
I'm actually not so sure what the correct patterns for this are, but I normally go with the following approach (something like the .NET Stream or SafeHandle classes do):
Your AveragePeriodDaysService really seems to take control of the context (it stores it in a private readonly field). So actually this class should implement IDisposable and dispose of the context itself.
On the other hand, you might want to use a single context for different "service" classes without always creating a new one. So it would be annoying if these classes always dispose the context.
So my way of implementing it would be something like this:
public class AveragePeriodDaysService : IDisposable
{
private readonly MyDbContext _ctx;
private readonly bool _ownContext;
public AveragePeriodDaysService(MyDbContext ctx, bool ownContext)
{
_ctx = ctx;
_ownContext = ownContext;
}
protected virtual void Dispose(bool disposing)
{
if (disposing) GC.SuppressFinalize(this);
if (_ownContext) _ctx.Dispose();
}
public void Dispose()
{
Dispose(true);
}
Then you can decide if the created instance should be responsible for disposing the context or if the creator needs to keep control.
Of course, if the created instance should take control, you need to properly dispose of this instance.

Is it dangerous to use a memorystream as a private field

Is it dangerous to use a memorystream as a private field in an instance class?
The class implements IDisposable:
class MyIDisposableClass:IDisposable{
private MemoryStream _stream;
//do stuff with _stream
void Dispose(){
_stream.Close();
_stream.Dispose();//does this statement make sense here ?
}
}
and will be used like this:
using(MyIDisposableClass() bla=new MyIDisposableClass())
{...}
Is that good approach or should I do something else, to give all class member access to that kind of information?
You're fine as long as you are wrapping your object in a using
After the using block the object's disposed method will get called. As long as you clean up everything you'll be fine.
And if you are worried about when it will be called the code here will show you.
using System;
public class DisposableExample : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Before Disposing");
using(var disposableObj = new DisposableExample())
{
Console.WriteLine("Inside Using Statement");
}
Console.WriteLine("After Disposing");
}
}
This will print out
Before Disposing
Inside Using Statement
Disposed
After Disposing
See fiddle here

How to implement IDisposable interface in a class inherited from SocketAsyncEventArgs

I work on a huge project in C# .NET 4.0. There is a custom class inherited from System.Net.Sockets.SocketAsyncEventArgs class. Something like the following:
public class SocketTaskArgs : SocketAsyncEventArgs
{
public SocketTaskArgs()
{
Completed += someEventhHandler;
}
public void CleanUp()
{
Completed -= someEventhHandler;
}
/*
There is a lot of code here that is unimportant at the moment.
*/
}
So, I wanted to move the content of CleanUp() method to Dispose(bool) method.
As first, I checked the source code of the base class - SocketAsyncEventArgs (using Go To Definition so that I saw metadata as source). I found out, this class implements IDisposable interface. Nice, I just need to override the Dispose(bool) method, don't I? (See IDisposable Interface on MSDN, the "IDisposable and the inheritance hierarchy" section, for more details). Nothing new for me... Unfortunately, the SocketAsyncEventArgs class is implemented as following:
public class SocketAsyncEventArgs : EventArgs, IDisposable
{
public void Dispose();
//some other stuff here
}
That means, there is no way how to override Dispose(bool) method, as it's implemented as private instead of protected... What is the reason for this?
Next, I read about SocketAsyncEventArgs.Dispose() method on MSDN. The funny thing is that, it contains the following section:
Notes to Inheritors
Dispose can be called multiple times by other
objects. When overriding Dispose(Boolean), be careful not to reference
objects that have been previously disposed of in an earlier call to
Dispose. For more information about how to implement Dispose(Boolean),
see Implementing a Dispose Method.
Wait... what?
When overriding Dispose(Boolean), ...
How am I supposed to override Dispose(Boolean)?
What is the recommended way to implement IDisposable interface in this case?
There doesn't seem to be anything stopping you from implementing IDisposable on your child class, take this example:
public class DisposableParent : IDisposable
{
public void Dispose()
{
Console.WriteLine("The parent was disposed.");
}
}
public class DisposableChild : DisposableParent, IDisposable
{
public new void Dispose()
{
base.Dispose();
Console.WriteLine("The child was disposed.");
}
}
public class Program
{
public static void Main()
{
using (DisposableChild c = new DisposableChild()) { }
Console.ReadKey(true);
}
}
Gives the following output:
The parent was disposed.
The child was disposed.
The compiler warns about hiding the dispose of the parent class in the child, so using the new operator gets rid of that warning, just make sure to call the base class Dispose from the child class (and implement it the right way).
The dispose for the child would become something like:
public class DisposableChild : DisposableParent, IDisposable
{
private bool _disposed = false;
public new void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (!_disposed)
{
base.Dispose();
Console.WriteLine("The child was disposed.");
_disposed = true;
}
}
}
}
And yes, this still works if you do something like:
using (DisposableParent p = new DisposableChild())
{
}
But something like this can break it:
public class Program
{
public static void Main()
{
DisposableChild c = new DisposableChild();
DisposeOfIt(c);
Console.ReadKey(true);
}
public static void DisposeOfIt(DisposableParent p)
{
p.Dispose();
}
}
Only prints out that the parent was disposed. So if you used this method you would have to be careful about controlling the lifetime of your objects.

When/how is IDisposable.Dispose called?

Given the following class which implements both Dispose and IDisposable.Dispose:
internal class DisposableClass : IDisposable
{
public void Dispose()
{
}
void IDisposable.Dispose()
{
}
}
When I make a call to DisposeableClass.Dispose (through an instance of the class), the public void Dispose is called:
DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
newClass.Dispose();
}
If you change the try-finally to a using statement, IDisposable.Dispose is called.
using (DisposableClass newClass = new DisposableClass())
{
}
But NOT the IDisposable.Dispose which I defined.
The compiler translates the using-statement to ((IDisposable)newClass).Dispose(). The full methodname shows it to be from System.IDisposable.Dispose.
IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()
When will my custom implementation of IDisposable.Dispose be called?
Note that I am not using this actual implementation and I get that this should not be used. But I am still curious as to which implementation gets called when.
If I'd have a different implementation for each of the Dispose methods; which implementation would be called when?
Your approach to disposing is wrong. You should look at The Dispose Pattern to understand how to do this properly.
However... To answer your question how / why are they called...
Your public void Dispose() is being called when you say newClass.Dispose(); because it is the best "match" for what you have asked. By that (and without getting too complicated) it is because it is the highest in the hierarchy and therefore the one the compiler expects you to mean because it is the most specific. If you hadn't created your own it would have gone through hierarchy to find a Dispose method.
When you wrap with using the compiler produces code similar to this:
DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
((IDisposable)newClass).Dispose();
}
This will therefore call the IDiposable version explicitly.
UPDATE
Full working sample below that will give this output:
Manually calling newClass.Dispose();
public void Dispose() being called.
Now wrapped in using...
void IDisposable.Dispose() being called.
Manually calling IDisposable.Dispose();
void IDisposable.Dispose() being called.
Full working code (paste this inside a console app and run):
using System;
namespace zPlayGround
{
class Program
{
static void Main()
{
Console.WriteLine("Manually calling newClass.Dispose();");
var newClass = new DisposableClass();
try
{
}
finally
{
newClass.Dispose();
}
Console.WriteLine("Now wrapped in using...");
using (var usingClass = new DisposableClass())
{
}
Console.WriteLine("Manually calling IDisposable.Dispose();");
var demoClass = new DisposableClass();
try
{
}
finally
{
((IDisposable)newClass).Dispose();
}
Console.ReadKey();
}
}
internal class DisposableClass : IDisposable
{
public void Dispose()
{
Console.WriteLine("public void Dispose() being called.\r\n");
}
void IDisposable.Dispose()
{
Console.WriteLine("void IDisposable.Dispose() being called.\r\n");
}
}
}

How to know whether a class method was called internally or remotely in .NET Remoting?

I have a class which needs to behave differently when being called remotely via .Net remoting. How can I determine, inside the class, if this is the case?
class RemoteClass : MarshalByRefObject
{
public void SomeMethod ()
{
if (ConditionWhatINeed) //If this method was called internally/remotely
{
//Do one stuff
}
else
{
//Do another suff
}
}
you may want to have a look at the RemotingServices.IsObjectOutOfContext Method. it also has an example you may find useful. of course, because you'll be calling this method server-side on 'this' it will never be seen as a remoting object but if you add a parameter to your method than that parameter will be in local context if not remoting and out of context when remoting (PS this is an unverified assumption on my account). Another useful helper may be the RemotingServices.IsTransparentProxy Method.
There may be a way using one of the *Services objects under the System.Runtime.Remoting hierarchy, as mtijn indicated. However, you have deep problems in your object model. Having dual responsibility on objects is bad practice, difficult to maintain and difficult to understand. Why not rather expose a dedicated 'remote' object; the following sample demonstrates it:
class Program
{
static void Main(string[] args)
{
InitializeRemoting();
var remote = GetRemotingObject("localhost");
var local = new LocalClass();
remote.SomeMethod();
local.SomeMethod();
Console.ReadLine();
}
static void InitializeRemoting()
{
var c = new TcpServerChannel(9000);
ChannelServices.RegisterChannel(c, false);
WellKnownServiceTypeEntry entry = new WellKnownServiceTypeEntry
(
typeof(RemoteClass),
"LocalClass", // Lie about the object name.
WellKnownObjectMode.Singleton
);
RemotingConfiguration.RegisterWellKnownServiceType(entry);
}
static LocalClass GetRemotingObject(string serverName)
{
TcpClientChannel channel = new TcpClientChannel("tcp-client", new BinaryClientFormatterSinkProvider());
ChannelServices.RegisterChannel(channel, false);
return (LocalClass)Activator.GetObject
(
typeof(LocalClass), // Remoting will happily cast it to a type we have access to.
string.Format("tcp://{0}:9000/LocalClass", serverName)
);
}
}
public class LocalClass : MarshalByRefObject
{
public void SomeMethod()
{
OnSomeMethod();
}
protected virtual void OnSomeMethod()
{
// Method called locally.
Console.WriteLine("Local!");
}
}
// Note that we don't need to (and probably shouldn't) expose the remoting type publicly.
class RemoteClass : LocalClass
{
protected override void OnSomeMethod()
{
// Method called remotely.
Console.WriteLine("Remote!");
}
}
// Output:
// Remote!
// Local!
Edit: To answer your question directly, even though what you are trying to achieve is bad practice, duplicate my code and simply provide a virtual bool IsLocal { get { return true; } } on the local class and override it on the remote class. You can then use the property in your if statements.
Edit: If you server and your clients needs to share the exact same instance of the class you should use the Facade Pattern. For example:
class CommonImplementation
{
public static readonly CommonImplementation Instance = new CommonImplementation();
private CommonImplementation() { }
public void SomeMethod(string someArg, bool isServerCall)
{
if (isServerCall)
{
Console.WriteLine("Remote! {0}", someArg);
}
else
{
Console.WriteLine("Local! {0}", someArg);
}
}
}
// These two classes are the facade.
public class LocalClass : MarshalByRefObject
{
public virtual void SomeMethod(string someArg)
{
CommonImplementation.Instance.SomeMethod(someArg, false);
}
}
class RemoteClass : LocalClass
{
public override void SomeMethod(string someArg)
{
CommonImplementation.Instance.SomeMethod(someArg, true);
}
}

Categories

Resources