I'm defining my DbConntextObj
_container.RegisterType<IDbConntextObj, DbConntextObj>(new HttpContextLifetimeManager<DbConntextObj>());
Unity is not calling the RemoveValue() on the lifetimemanager
I have one Dbcontext for multiple repositories.
My lifetimemanager looks like this:
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
private readonly string _itemName = typeof(T).AssemblyQualifiedName;
public override object GetValue()
{
return HttpContext.Current.Items[_itemName];
}
public override void RemoveValue()
{
var disposable = GetValue() as IDisposable;
HttpContext.Current.Items.Remove(_itemName);
if (disposable != null)
disposable.Dispose();
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[_itemName] = newValue;
}
public void Dispose()
{
RemoveValue();
}
}
Is it a bad thing that DbContext Dispose is not being called?
Is there a workaround For Unity and MVC3?
Try this.
public class MvcApplication : HttpApplication
{
private IUnityContainer unityContainer;
private HttpContextDisposableLifetimeManager ContextLifeTimeManager;
/// <summary>
/// The start method of the application.
/// </summary>
protected void Application_Start()
{
unityContainer = new UnityContainer();
ContextLifeTimeManager = new HttpContextDisposableLifetimeManager();
//for some reason this event handler registration doesn't work, meaning we have to add code to
//Application_EndRequest as below...
//this.EndRequest += new EventHandler(ContextLifeTimeManager.DisposingHandler);
unityContainer.RegisterType<IUnitOfWork, EFUnitOfWork>(ContextLifeTimeManager);
unityContainer.RegisterType<IRepository<ShoppingCart>, ShoppingCartRepository>(new ContainerControlledLifetimeManager());
}
//this seems hackish, but it works, so whatever...
protected void Application_EndRequest(Object sender, EventArgs e)
{
if (ContextLifeTimeManager != null)
{
ContextLifeTimeManager.RemoveValue();
}
}
}
Then in your LifeTimeManager implementation.
public class HttpContextDisposableLifetimeManager : LifetimeManager, IDisposable
{
const string _itemName = typeof(T).AssemblyQualifiedName;
public void DisposingHandler(object source, EventArgs e)
{
RemoveValue();
}
public override object GetValue()
{
return HttpContext.Current.Items[_itemName];
}
public override void RemoveValue()
{
Dispose();
HttpContext.Current.Items.Remove(_itemName);
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[_itemName] = newValue;
}
public void Dispose()
{
var obj = (IDisposable)GetValue();
obj.Dispose();
}
}
Related
When I call IKernel.Dispose() in the [TestCleanup] method of my DataTest, my application is crashing because the first object to be disposed is still in use by another object.
This code reproduces the issue:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ninject;
using Ninject.Modules;
[TestClass]
public class NinjectDisposeIssue
{
private IKernel kernel;
[TestInitialize]
public void TestInitialize()
{
kernel = new StandardKernel(new Module());
}
[TestCleanup]
public void TestCleanup()
{
kernel.Dispose();
}
[DataTestMethod]
[DataRow]
[DataRow]
public void DataTestMethod()
{
var parent = kernel.Get<Parent>();
parent.Run();
}
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<Parent>().ToSelf().InSingletonScope();
Bind<Service>().ToSelf().InSingletonScope();
Bind<Database>().ToSelf().InSingletonScope();
// create 2 workers
Bind<Worker>().ToSelf().InSingletonScope();
Bind<Worker>().ToSelf().InSingletonScope();
}
}
public class Parent
{
private readonly Service service;
private readonly IEnumerable<Worker> workers;
public Parent(Service service, IEnumerable<Worker> workers)
{
this.service = service;
this.workers = workers;
}
public void Run()
{
for (var i = 0; i < 2; i++)
{
foreach (var worker in workers)
{
worker.StartWork();
}
service.DoSomething();
}
}
}
public class Service
{
private readonly Database database;
public Service(Database database)
{
this.database = database;
}
public void DoSomething()
{
var value = database.Get();
// do something with the value
}
}
public class Worker : IDisposable
{
private readonly Database database;
private Task workTask;
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private bool disposedValue;
public Worker(Database database)
{
this.database = database;
}
public void StartWork()
{
if (workTask == null)
{
workTask = Task.Run(WorkLoop);
}
}
private void WorkLoop()
{
while (!cancellationTokenSource.Token.IsCancellationRequested)
{
var value = database.Get();
// do some work with the value...
}
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
cancellationTokenSource.Cancel();
workTask.Wait();
workTask.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
public class Database : IDisposable
{
private readonly ThirdPartyDb thirdPartyDb = new ThirdPartyDb();
private bool disposedValue;
public string Get()
{
return thirdPartyDb.Get("foo");
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
thirdPartyDb.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
public class ThirdPartyDb : IDisposable
{
private bool isDisposed = false;
public void Dispose()
{
isDisposed = true;
}
public string Get(string key)
{
if (isDisposed)
{
throw new ObjectDisposedException(nameof(ThirdPartyDb));
}
return "bar";
}
}
The Dispose() method of the Database object is being called before the Dispose() method of the 2 Workers.
Question: Is there something I can do in the bindings to force the Workers to be disposed before the Database or is the way I have this configured fundamentally wrong?
As a simple solution, you can just add another CancellationTokenSource to your Database. This way you'll make sure that the thirdPartyDb is not getting called after disposal.
public class Database : IDisposable
{
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly ThirdPartyDb thirdPartyDb = new ThirdPartyDb();
private bool disposedValue;
public string Get()
{
if (cancellationTokenSource.Token.IsCancellationRequested) return ""; //Return anything acceptable for you
return thirdPartyDb.Get("foo");
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
cancellationTokenSource.Cancel();
thirdPartyDb.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
I have a sealed class. It has a property
'
private IObservable<AnotherClass> observable
'.
I want to make this class as an observer and monitor the change in the above property.
I want to call onNext() whenever there is a change in this property.
I want to call a custom method1() in .onNext(). like onNext( call Method1(pass the observable data)).
Since this is a sealed class, I cannot use Virtual onNext() as I found in many examples.
How do I achieve these?
Implement IObserver<AnotherClass> and subscribe to the observable?
public sealed class AnObserver : IObserver<AnotherClass>
{
private readonly IObservable<AnotherClass> observable;
public AnObserver()
{
observable = ...;
observable.Subscribe(this);
}
void IObserver<AnotherClass>.OnCompleted() { }
void IObserver<AnotherClass>.OnError(Exception error) { }
void IObserver<AnotherClass>.OnNext(AnotherClass value)
{
Method1(value);
}
public void Method1(AnotherClass value)
{
...
}
}
Here's how I would tackle this situation.
public sealed class ThisClass : IDisposable
{
private readonly IObservable<AnotherClass> observable;
private readonly IDisposable subscription;
public ThisClass()
{
observable = ...;
subscription = observable.Subscribe(x => Method1(x));
}
private void Method1(AnotherClass value)
{
...
}
private bool disposedValue = false;
void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
subscription.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
}
This doesn't expose anything unnecessary to the outside world and it cleans up on dispose.
Hi so what I wanted is something along the lines of, is it possible in c#? ~
(and without using reflection?)
Current:
protected override void AddTelegrams()
{
TelegramPublisher.Subscribe<Telegram1>(TelegramReceived);
TelegramPublisher.Subscribe<Telegram2>(TelegramReceived);
TelegramPublisher.Subscribe<Telegram3>(TelegramReceived);
}
protected override void RemoveTelegrams()
{
TelegramPublisher.UnSubscribe<Telegram1>(TelegramReceived);
TelegramPublisher.UnSubscribe<Telegram2>(TelegramReceived);
TelegramPublisher.UnSubscribe<Telegram3>(TelegramReceived);
}
Objective:
private IEnumerable<Type> GetListTelegramTypes()
{
return new List<Type>()
{
typeof(Telegram1),
typeof(Telegram2),
typeof(Telegram3)
};
}
protected override void AddTelegrams()
{
foreach (var type in GetListTelegramTypes())
TelegramPublisher.Subscribe<type>(TelegramReceived);
}
protected override void RemoveTelegrams()
{
foreach (var type in GetListTelegramTypes())
TelegramPublisher.UnSubscribe<type>(TelegramReceived);
}
Also Subscribe and Unsubscribe generic type mas be or inherit from "Telegram"...
If you don't want to use reflection, you can do something like:
public interface ITelegramSubscriber
{
void Subscribe(TelegramReceivedHandler handler);
void Unsubscribe(TelegramReceivedHandler handler);
}
public class TelegramSubscriber<T> : ITelegramSubscriber
{
public void Subscribe(TelegramReceivedHandler handler) =>
TelegramPublisher.Subscribe<T>(handler);
public void Unsubscribe(TelegramReceivedHandler handler) =>
TelegramPublisher.Unsubscribe<T>(handler);
}
Then:
private IEnumerable<ITelegramSubscriber> GetListTelegramSubscribers()
{
return new List<ITelegramSubscriber>()
{
new TelegramSubscriber<Telegram1>(),
new TelegramSubscriber<Telegram2>(),
new TelegramSubscriber<Telegram3>(),
new TelegramSubscriber<Telegram4>(),
};
}
protected override void AddTelegrams()
{
foreach (var subscriber in GetListTelegramSubscribers())
subscriber.Subscribe(TelegramReceived);
}
protected override void RemoveTelegrams()
{
foreach (var subscriber in GetListTelegramSubscribers())
subscriber.Unsubscribe(TelegramReceived);
}
This assumes that you have one TelegramReceivedHandler method type which handles all telegrams. If you in fact have multiple overloads (it isn't clear from your question), then you probably want something like:
public interface ITelegramSubscriber
{
void Subscribe();
void Unsubscribe();
}
public class TelegramSubscriber<T> : ITelegramSubscriber
{
private readonly TelegramReceivedHandler<T> handler;
public TelegramSubscriber(TelegramReceivedHandler<T> handler) => this.handler = handler;
public void Subscribe() => TelegramPublisher.Subscribe<T>(handler);
public void Unsubscribe() => TelegramPublisher.Unsubscribe<T>(handler);
}
Then:
private IEnumerable<ITelegramSubscriber> GetListTelegramSubscribers()
{
return new List<ITelegramSubscriber>()
{
new TelegramSubscriber<Telegram1>(TelegramReceived),
new TelegramSubscriber<Telegram2>(TelegramReceived),
new TelegramSubscriber<Telegram3>(TelegramReceived),
new TelegramSubscriber<Telegram4>(TelegramReceived),
};
}
protected override void AddTelegrams()
{
foreach (var subscriber in GetListTelegramSubscribers())
subscriber.Subscribe();
}
protected override void RemoveTelegrams()
{
foreach (var subscriber in GetListTelegramSubscribers())
subscriber.Unsubscribe();
}
I want to Override base class methods in derived class and then do something in derived class. therefore the base class method be invoked with its generic type . Then I aim to fire the derived class method which is overridden.
I have below codes :
public class Service<T> : Interface.IService<T> where T : class
{
public virtual event System.EventHandler<EntitySavingEventArgs<T>> BeforeSavingRecord;
public Service()
{
}
public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
{
}
private readonly DbContext _dbContext;
public Service(DbContext dbContext)
{
_dbContext = dbContext;
}
public virtual void Create(T item)
{
if (item == null)
throw new ArgumentNullException("item");
BeforeSavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
_dbContext.Set(typeof(T)).Add(item);
_dbContext.SaveChanges();
}
}
and in its derrived classes I have something like this :
[Service]
public partial class BankBusiness : Service<Bank>, IBankBusiness
{
public BankBusiness()
: base(ContainerManager.Container.Resolve<MyContext>())
{
}
public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
{
//Do something with entity item before saving
base.OnBeforeSavingRecord(sender, e);
}
}
And then in my controllers when I call
bankBiz.Create(new Bank() { ... });
I want to fire bankBiz (derrived class) overridden method (OnBeforeSavingRecord) which is registered to BeforeSavingRecord event.
I donot know if my scenario is correct and if it is right how i can fire it.
if it is not correct what I should do.
I had a similar pattern implemented in the base class I did it in a way like this:
Base:
public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
{ }
and in the derived class I had exactly the call that you use:
Derivied:
public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
{
//Do something with entity item before saving
base.OnBeforeSavingRecord(sender, e);
}
To fire the event in my case it was sufficient to just call
OnBeforeSavingRecord(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
and the whole scenario worked for me.
EDIT:
Calling OnBeforeSavingRecord will executed the code in the overriden method of the derived class if you call it from an instance of the derived class!
If I understand you right you want to fire the event in the method Create but want the event code of the derived class executed. It will be if the event is overridden like in your case. You could test it with this simple Console application: (just copy paste and run)
public class Service
{
public virtual event System.EventHandler<EventArgs> BeforeSavingRecord;
public virtual void OnBeforeSavingRecord(object sender, EventArgs e)
{
Console.WriteLine("Base: OnBeforeSavingRecord method call");
}
public virtual void Create(object item)
{
Console.WriteLine("Base: Create method call");
// this will call the method of the derived class! if you call it from an instance of the derived class
OnBeforeSavingRecord(this, new EventArgs());
}
}
public partial class BankBusiness : Service
{
public override void OnBeforeSavingRecord(object sender, EventArgs e)
{
//Do something with entity item before saving
Console.WriteLine("Derived Class OnBeforeSavingRecord CALL");
base.OnBeforeSavingRecord(sender, e);
}
}
static void Main(string[] args)
{
BankBusiness bankBiz = new BankBusiness();
bankBiz.Create(new object());
Console.ReadKey();
}
#Mong Zhu your solution works but not for my scenario . I came up with the below solution
public class Service<T> : Interface.IService<T> where T : class
{
Interface.IService<T> implementation;
public virtual event System.EventHandler<EntitySavingEventArgs<T>> BeforeSavingRecord;
public virtual event System.EventHandler<EntitySavingEventArgs<T>> SavingRecord;
public virtual event System.EventHandler<EntitySavingEventArgs<T>> RecordSaved;
public void PopulateEvents(Interface.IService<T> _implementation)
{
implementation = _implementation;
implementation.BeforeSavingRecord += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnBeforeSavingRecord);
implementation.SavingRecord += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnSavingRecord);
implementation.RecordSaved += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnRecordSaved);
}
public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
{
}
public virtual void OnSavingRecord(object sender, EntitySavingEventArgs<T> e)
{
}
public virtual void OnRecordSaved(object sender, EntitySavingEventArgs<T> e)
{
}
private readonly DbContext _dbContext;
public Service(DbContext dbContext)
{
_dbContext = dbContext;
}
public virtual void Create(T item)
{
if (item == null)
throw new ArgumentNullException("item");
BeforeSavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
_dbContext.Set(typeof(T)).Add(item);
SavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
_dbContext.SaveChanges();
RecordSaved?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
}
}
and the derived class :
[Service]
public partial class BankBusiness : Service<Bank>, IBankBusiness
{
public BankBusiness()
: base(ContainerManager.Container.Resolve<MyContext>())
{
base.PopulateEvents(this);
}
public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
{
base.OnBeforeSavingRecord(sender, e);
}
}
which the point is
base.PopulateEvents(this);
I'm trying to implement Unit of Work and Generic Repository by following this great article. Only difference is that I have multiple databases context in my app. I came up with the below implementation but it seems awkward to say the least. What's the best way to do it ?
public class UnitOfWork : IDisposable
{
private MainDBDataContext MainDBDataContext = new MainDBDataContext();
private ReferenceDBDataContext ReferenceDBDataContext = new ReferenceDBDataContext();
private ProjectDBDataContext projectDBDataContext = new ProjectDBDataContext();
private VehicleRepository vehicleRepository;
private AccountRepository accountRepository;
public VehicleRepository VehicleRepository
{
get
{
if (this.vehicleRepository == null)
{
this.vehicleRepository = new VehicleRepository(projectDBDataContext,ReferenceDBDataContext);
}
return vehicleRepository;
}
}
public AccountRepository AccountRepository
{
get {
if (this.accountRepository == null)
{
this.accountRepository = new AccountRepository(projectDBDataContext);
}
return accountRepository;
}
}
public void Save()
{
projectDBDataContext.SubmitChanges();
ReferenceDBDataContext.SubmitChanges();
MainDBDataContext.SubmitChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
projectDBDataContext.Dispose();
MainDBDataContext.Dispose();
ReferenceDBDataContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}