For example I have this class:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public IProductRepository Products { get; private set; }
public ICategoryRepository Categories { get; private set; }
public IPhotoRepository Photos { get; private set; }
public UnitOfWork(ApplicationDbContext context, IProductRepository productRepository,
ICategoryRepository categoryRepository, IPhotoRepository photoRepository)
{
_context = context;
Products = productRepository;
Categories = categoryRepository;
Photos = photoRepository;
}
public int Complete()
{
return _context.SaveChanges();
}
public Task<int> CompleteAsync()
{
return _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
public async ValueTask DisposeAsync()
{
await _context.DisposeAsync();
}
}
With a such Interface:
public interface IUnitOfWork : IDisposable, IAsyncDisposable
{
IProductRepository Products { get; }
ICategoryRepository Categories { get; }
IPhotoRepository Photos { get; }
int Complete();
Task<int> CompleteAsync();
}
Is it right to have both Async and Sync methods? Also what method will be called during disposal if I'm using DI in asp net core for example.
The DisposeAsyncCore() method is intended to perform the asynchronous cleanup of managed resources or for cascading calls to DisposeAsync() . It encapsulates the common asynchronous cleanup operations when a subclass inherits a base class that is an implementation of IAsyncDisposable.
When should you implement only IDisposable
?
IDispoable
is the more standard and default interface, and supported by nearly all frameworks since the very beginning or soon thereafter. If your class or a derived class of your class doesn't need to release resources asynchronously then consider only implementing IDisposable
. For example, SemaphoreSlim
doesn't implement IAsyncDisposable
.
When can you get away with only implementing IAsyncDisposable
?
Note: This applies more to situations where you are in control or aware of how your objects will be instantiated and destroyed. For example, if you are writing an executable (as opposed to a library) wherein you are more in control of your overall environment and code's destiny.
You should implement IAsyncDisposable
if you foresee that your class or a derived class of your class will need or may need to release resources asynchronously.
When should you implement both IAsyncDisposable
and IDisposable
?
Note: Below applies more as best practice and recommended approach for libraries as they are typically not in control of the code that creates instances of the types defined in the library.
Ideally, you should implement both IAsyncDisposable
and IDisposable
. In other words, IAsyncDisposable
shouldn't be considered as a replacement for IDisposable
.
Why?
IAsyncDisposable
. Most, of course, do but not all dependency injection systems are created equal. If you are writing a library, you don't know how your objects will get created.DisposeAsync
to make it sync. The caller's dispose call will be more like yourDisposableObject.DisposeAsync().GetAwaiter().GetResult()
.Here's a quote from the official Microsoft MSDN.
It is typical when implementing the IAsyncDisposable interface that classes will also implement the IDisposable interface. A good implementation pattern of the IAsyncDisposable interface is to be prepared for either synchronous or asynchronous dispose. All of the guidance for implementing the dispose pattern also applies to the asynchronous implementation.
Other minor recommendations: Consider implementing your Dispose()
and DisposeAsync()
as virtual if you foresee your class's derived classes will have resources that may need disposing. Otherwise, consider making your class sealed
.
Good examples
References
Regardless of your AspNetCore concern; yes, it is perfectly ok to have both Sync and Async methods implemented in one class.
But, having interface chains (one interface mandates to implement another one) is considered as not clean-code.
see this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With