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);
Related
I have classes Room and Iceball. Iceball and IceShard are inherited from class Magic.
When I add new magic to room, room subscribes to event CreateNewMagic magic, but after exiting from method event is still null.
Iceball after collision should creates ice shards in the room with the help of event, but because the event is null room cant spawn ice shards
Class Room
{
public readonly List<Magi> MagicInRoom;
public void SpawnMagic(Magic magic)
{
MagicInRoom.Add(magic);
magic.CreateNewMagic += SpawnMagic;
}
}
Class Magic, IceBall and IceShard
public abstract class Magic
{
public delegate void MagicHandler(Magic magic);
public event MagicHandler CreateNewMagic;
public virtual void OnCollisionEnter()
{
if (...)
{
...
}
}
}
public class IceBall : Magic
{
public delegate void MagicHandler(Magic magic);
public event MagicHandler CreateNewMagic;
public override void OnCollisionEnter()
{
if (...)
{
var iceShards = CreateIceShards();
foreach (var iceShard in iceShards)
if (CreateNewMagic != null) //ALWAYS IS NULL
CreateNewMagic(iceShard);
}
}
}
public class IceShard : Magic
{
...
}
Event should be abstract
public abstract class Magic
{
public delegate void MagicHandler(Magic magic);
public abstract event MagicHandler CreateNewMagic;
public virtual void OnCollisionEnter()
{
if (...)
{
...
}
}
}
public class IceBall : Magic
{
public override event MagicHandler CreateNewMagic;
public override void OnCollisionEnter()
{
if (...)
{
var iceShards = CreateIceShards();
foreach (var iceShard in iceShards)
if (CreateNewMagic != null) //ALWAYS IS NULL
CreateNewMagic(iceShard);
}
}
}
public class IceShard : Magic
{
public override event MagicHandler CreateNewMagic;
}
Currently I have made a design where my BaseClass is the guideline of how my program has to behave. I have made an abstract method DoWork() , the inheritors have to implement this method.
The thing is Class C overrides Setup() so it doesn't need DoWork() anymore. Now I am left with a throw new NotImplementedException();
Question: Is there a way how to improve my design so I won't have those methods with NotImplementedException?
public abstract class BaseClass
{
public virtual void Setup()
{
DoWork();
FinnishWork();
Environment.Exit(0);
}
public abstract void DoWork();
public abstract void FinnishWork();
}
public class A : BaseClass
{
public override void DoWork()
{
Console.WriteLine('A');
}
public override void FinnishWork()
{
Console.WriteLine('FinnishA');
}
}
public class B : BaseClass
{
public override void DoWork()
{
Console.WriteLine('B');
}
public override void FinnishWork()
{
Console.WriteLine('FinnishB');
}
}
public class C : BaseClass
{
public override void Setup()
{
FinnishWork();
Console.WriteLine('C');
}
public override void DoWork()
{
throw new NotImplementedException();
}
public override void FinnishWork()
{
Console.WriteLine('FinnishC');
}
}
As class C doesn't implement DoWork() it shouldn't really inherit from your abstract class.
You can only inherit from one class, but you can implement many interfaces.
In many ways it is simpler to deal with interfaces than abstract classes. Base classes, whether abstract or not really come into their own if they perform some function that you may wish to provide to you inheriting classes. An abstract class with empty methods isn't any better than an interface.
Consider something like:
public interface IDoWork
{
void DoWork();
}
public interface IBase
{
void Setup();
void FinnishWork();
}
public abstract class BaseClass : IBase, IDoWork
{
public virtual void Setup()
{
DoWork();
FinnishWork();
Environment.Exit(0);
}
public abstract void FinnishWork();
public abstract void DoWork();
}
public class A : BaseClass
{
public override void DoWork()
{
Console.WriteLine('A');
}
public override void FinnishWork()
{
Console.WriteLine("FinnishA");
}
}
public class B : BaseClass
{
public override void DoWork()
{
Console.WriteLine('B');
}
public override void FinnishWork()
{
Console.WriteLine("FinnishB");
}
}
public class C : IBase
{
public void Setup()
{
FinnishWork();
Console.WriteLine('C');
}
public void FinnishWork()
{
Console.WriteLine("FinnishC");
}
}
Examples in use:
IBase instanceA = new A();
BaseClass instanceB = new B();
IBase instanceC = new C();
instanceA.Setup();
instanceB.Setup();
instanceC.Setup();
instanceB.DoWork();
You're inheriting in too few steps. You need BaseClassLite and BaseClassHeavy to make this work.
Start with this:
public abstract class BaseClassLite
{
public virtual void Setup()
{
FinnishWork();
Environment.Exit(0);
}
public abstract void FinnishWork();
}
public abstract class BaseClassHeavy : BaseClassLite
{
public override void Setup()
{
DoWork();
base.Setup();
}
public abstract void DoWork();
}
(Or give them more meaningful names.)
Then you implement your classes like this:
public class A : BaseClassHeavy
{
public override void DoWork()
{
Console.WriteLine("A");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishA");
}
}
public class B : BaseClassHeavy
{
public override void DoWork()
{
Console.WriteLine("B");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishB");
}
}
public class C : BaseClassLite
{
public override void Setup()
{
base.Setup();
Console.WriteLine("C");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishC");
}
}
The idea to have a Setup method in BaseClass while having 2 abstracts methods to implement is good (it is even given a name: template method pattern).
However there is one problem lying in how Setup() is declared in BaseClass: you made it virtual which goes against the principle that you want to enforce:
BaseClass is the guideline of how my program has to behave
It is now possible to override it (like you did in C) and break the behavior you want to enforce.
First, remove virtual in BaseClass then override DoWork in C as follow:
public override void DoWork() { }
Having this kind of empty method is a sign of a flawed abstraction (does C really need to inherit from BaseClass ?) but I can't help more if you don't provide more context about the real meaning and names of these classes/methods.
Use a second base class to be inherited from class C:
public abstract class BaseBaseClass
{
public virtual void Setup()
{
FinnishWork();
Environment.Exit(0);
}
...
}
public abstract class BaseClass : BaseBaseClass
{
public abstract void DoWork();
...
}
public class C : BaseBaseClass {...}
I want to implement delegation pattern using delegates
public class Cat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public Cat() {
sound = new SoundDelegate(SomeClass.DoSound1);
}
public void DoSound() {
sound();
}
}
public class PussyCat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public PussyCat() {
sound = new SoundDelegate(SomeClass.DoSound2);
}
public void DoSound() {
sound();
}
}
public class SomeClass {
public static void DoSound1() {
Console.WriteLine("Sound 1");
}
public static void DoSound2() {
Console.WriteLine("Sound 2");
}
}
Does this code impelement the delegation pattern? I mean can I use delegates for implement delegation pattern or this way is incorrect.
And if the previous example is correct and I can use delegates to implement the delegation pattern and implement the observer pattern, then what is the difference between the observer pattern and the delegation pattern and what is similar?
The difference between delegation and observer patterns is a level of control your class has over the delegate/observer.
In case of delegate, it's assumed that your class has full control over how delegated class should be used. The observable class has no idea of how exactly it would be used by other classes.
It's also often assumed that observable class could have any number of observers while delegate is usually one.
I also simplified the code provided trying to avoid unnecessarily class PussyCat, so the original class could be configured to use any delegate in runtime.
You can also find CatObservable class to understand the idea of observable-observer implementation.
class Program
{
static void Main(string[] args)
{
Cat cat1 = new Cat(SomeClass.DoSound1);
Cat cat2 = new Cat(SomeClass.DoSound2);
CatObservable cat3 = new CatObservable();
cat3.Sound += Cat3_Sound;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound1(); } ;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound2(); };
}
private static void Cat3_Sound(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
public class Cat
{
public delegate void SoundDelegate();
public SoundDelegate Sound { get; set; }
public Cat(SoundDelegate soundDelagate)
{
Sound = soundDelagate;
}
protected void DoSound()
{
if (Sound!=null)
Sound();
}
}
public class CatObservable
{
public event EventHandler Sound;
public CatObservable()
{
}
protected void DoSound()
{
if (Sound != null)
Sound(this, EventArgs.Empty);
}
}
public class SomeClass
{
public static void DoSound1()
{
Console.WriteLine("Sound 1");
}
public static void DoSound2()
{
Console.WriteLine("Sound 2");
}
}
I have two Projects one is a Winform application another is a Class library. I have added a reference to the class Library in Winform and called a method of the class library. Now I want to call a different method in winform application from class library but I can't add a reference to winform to the class library.
IN CODE:-
public partial class Form1 : Form
{
private void btn_Click(object sender, EventArgs e)
{
A obj = new A();
obj.foo();
}
public string Test(par)
{
//to_stuff
}
}
and in Class library
class A
{
public void foo()
{
//Do_stuff
//...
Test(Par);
//Do...
}
}
You can achieve this by injecting Test into class A.
For example:
public partial class Form1 : Form
{
private void btn_Click(object sender, EventArgs e)
{
A obj = new A();
obj.foo(Test);
}
public string Test(string par)
{
//to_stuff
}
}
class A
{
public void foo(Func<string, string> callback)
//Do_stuff
//...
if (callback != null)
{
callback(Par);
}
//Do...
}
}
While the callback method from David is a sufficient solution, if your interactions gets more complex, I would use this approach
Create an inteface in your class libary
public interface ITester
{
string Test(string value);
}
Rewrite your code so class A expects an ITester interface
public class A
{
public A(ITester tester)
{
this.tester = tester;
}
public string foo(string value)
{
return this.tester.Test(value);
}
}
Implement your interface in Form1
public partial class Form1 : Form, ITester
{
private void btn_Click(object sender, EventArgs e)
{
A obj = new A(this);
obj.foo("test");
}
public string Test(string value)
{
//to_stuff
return value;
}
}
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();
}
}