I look at the definition of the public abstract class AddInBase : EntryPoint in an Excel 2007 Add-In project. This class is included in the project by default so I have no control over this class.
The interface
`
public interface EntryPoint
{
void BeginInit();
void EndInit();
void FinishInitialization();
void Initialize();
void InitializeDataBindings();
void OnShutdown();
void OnStartup();
}
contains only public methods.
But the realization of AddInBase includes protected virtual implementation of the OnShutdown() method:
public abstract class AddInBase : IAddInExtension, IExtension, EntryPoint, ISupportInitialize, IBindableComponent, IComponent, IDisposable
{
///
protected virtual void OnShutdown();
protected virtual void OnStartup();
///
}
How this can be?
Thanks for any clarification!
You have to explicitly implement the EntryPoint interface, since You are already using a protected method, the class AddInBase must satisfy the contract EntryPoint hence those are implemented explicitly
Example :
public interface EntryPoint
{
void BeginInit();
void EndInit();
void FinishInitialization();
void Initialize();
void InitializeDataBindings();
void OnShutdown();
void OnStartup();
}
public abstract class AddInBase : EntryPoint
{
void EntryPoint.OnShutdown()
{
OnShutdown();
}
void EntryPoint.OnStartup()
{
OnStartup();
}
protected virtual void OnShutdown()
{
throw new NotImplementedException();
}
protected virtual void OnStartup()
{
throw new NotImplementedException();
}
}
Related
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 {...}
Given the following classes structure, is there a way to prevent BaseMethod() from being called or seen from FinalClass?
public abstract class BaseClass
{
protected virtual void BaseMethod()
{
}
}
public class IntermediateClass : BaseClass
{
protected sealed override void BaseMethod()
{
base.BaseMethod();
}
private void IntermediateMethod()
{
BaseMethod();
}
}
public class FinalClass : IntermediateClass
{
protected void FinalMethod()
{
}
}
You could make BaseMethod internal and place FinalClass in a different assembly to BaseClass and IntermediateClass.
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 doing CLR wrapper. It builds successfully. Problem is that when I reference wrapper .dll in c# project RegisterMessageCallback method is totally absent. Here is what I see in metadata:
public class ATFeedWrapper : IDisposable
{
public ATFeedWrapper();
public sealed override void Dispose();
public void Login();
protected virtual void Dispose(bool A_0);
}
And here is wrapper class .h:
public ref class ATFeedWrapper
{
public:
ATFeedWrapper();
void Login();
void RegisterMessageCallback(void(*clbck)(string));
~ATFeedWrapper();
private:
ATFeedClient* client;
};
and .cpp:
ATFeedWrapper::ATFeedWrapper()
{
client = new ATFeedClient();
}
void ATFeedWrapper::Login()
{
client->Login();
}
void ATFeedWrapper::RegisterMessageCallback(void(*clbck)(string))
{
client->RegisterMessageCallback(*clbck);
}
ATFeedWrapper::~ATFeedWrapper()
{
delete client;
}
What's going on? Why is it missing?
I'm learning DirectX but I don't know C++ very well so I decided to use SharpDX instead. But I'm stuck on this part in C++ they use the address of a function in the TypedEventHandler, but I don't know how to write that in C#? Can anyone help?
ref class App sealed : public IFrameworkView
{
public:
virtual void Initialize(CoreApplicationView^ AppView)
{
AppView->Activated += ref new TypedEventHandler
<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
}
virtual void SetWindow(CoreWindow^ Window) {}
virtual void Load(String^ EntryPoint) {}
virtual void Run() {}
virtual void Uninitialize() {}
void OnActivated(CoreApplicationView^ CoreAppView, IActivatedEventArgs^ Args)
{
CoreWindow^ Window = CoreWindow::GetForCurrentThread();
Window->Activate();
}
};
My conversion so far
internal class App : IFrameworkView
{
public void Initialize(CoreApplicationView AppView)
{
// Call OnActivated() when the Activated event is triggered
AppView.Activated += new TypedEventHandler<CoreApplicationView, IActivatedEventArgs>(this,this.OnActivated);
}
public void SetWindow(CoreWindow Window) {}
public void Load(String EntryPoint) {}
public void Run() {}
public void Uninitialize() {}
public void OnActivated(CoreApplicationView CoreAppView, IActivatedEventArgs Args)
{
CoreWindow Window = CoreWindow.GetForCurrentThread();
Window.Activate();
}
}
You don't need the "this" argument for the C# event wireup:
public sealed class App : IFrameworkView
{
public virtual void Initialize(CoreApplicationView AppView)
{
AppView.Activated += new TypedEventHandler <CoreApplicationView, IActivatedEventArgs>(OnActivated);
}
public virtual void SetWindow(CoreWindow Window)
{
}
public virtual void Load(string EntryPoint)
{
}
public virtual void Run()
{
}
public virtual void Uninitialize()
{
}
public void OnActivated(CoreApplicationView CoreAppView, IActivatedEventArgs Args)
{
CoreWindow Window = CoreWindow.GetForCurrentThread();
Window.Activate();
}
}