I am confused in deciding whether I should use
a polymorphic (via overriding the virtual method A) method.
a delegate-type-parameterized method B.
an event C.
an instance of a class implementing an interface with a single method D. A Java's trick!
when writing callbacks.
using System;
namespace CallBack
{
interface IOptional
{
void D();
}
class Base
{
protected virtual void A() => Console.WriteLine("Base's extra jobs.");
public void Do(Action B = null, IOptional optional = null)
{
Console.WriteLine("Base's main jobs.");
// and call the optional jobs
A();
B?.Invoke();
C?.Invoke();
optional?.D();
}
public event Action C;
}
class Derived : Base
{
protected override void A()
{
base.A();
Console.WriteLine("Derived's extra jobs.");
}
}
class Optional : IOptional
{
public void D()
{
Console.WriteLine("D");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
d.C += () => Console.WriteLine("C");
d.Do(() => Console.WriteLine("B"), new Optional());
}
}
}
Question
Is there any commonly used guideline for agile programmers?
The use cases of the three seem quite distinct to me :)
The core idea is "who do you want to let know about the event".
If you want to allow everyone to be able to subscribe to it, use an event. This is also what most of .NET that I have experience with deal with callbacks.
By using the polymorphism approach, you only allow subclasses to know about the event. If some other object wants to do something when it happens, it can't, because it's not a subclass and can't override the method.
By using the delegate parameter approach, you limit the number of subscribers to 1. Any caller can subscribe to the event, but subscriber-event is now a one-to-one relationship.
Related
I'm using a series of Template Pattern classes that represent different types of events.
internal abstract class DayEndingEvent : Event
{
internal void OnDayEnding(object? sender, DayEndingEventArgs e)
{
if (IsHooked) OnDayEndingImpl(sender, e);
}
protected abstract void OnDayEndingImpl(object? sender, DayEndingEventArgs e);
}
This pattern ensures that the implementation only runs if the event is "hooked", which allows other parts of the application to activate/deactivate the event by calling Hook and Unhook methods from the base Event class.
internal abstract class Event
{
public bool IsHooked {get; private set;}
public bool Hook() => !IsHooked && (IsHooked = true);
public bool Unhook() => IsHooked && !(IsHooked = false);
}
(Event is obviously more complex than this, but this is enough to get the picture).
My EventManager can instantiate one of every implementation of this pattern and hook their OnDayEnding to the appropriate handler in an external API.
This has worked fine for a while, but now I have a new requirement to add prioritization to these classes. The only way to do so (and this is a limitation of the external API) is by adding attribute [EventPriority] to the event callback. But obviously I can't annotate OnDayEnding with a priority since that would set the priority of all implementations, which defeats the whole purpose.
The attribute will have no effect anywhere else but on the callback. The only other solution I can see is to remove the Impl and just make the callback itself abstract. But that means I'd have to manually check the IsHooked flag on every implementation, which is what I want to avoid.
So question is, can anybody sugest an alternative to this pattern that would both 1) allow me to have different implementations of the callback, to which I can add priority attributes, and 2) enforce the check for IsHooked?
There are two possibilities I have come across recently when I encountered a similar problem:
Option one, have an entry method that has the required attributes:
public class SpecificImplementationClass1 : BaseClass, IInitializer
{
[SomeAttribute]
public void CallMeToInitiate(SomeType input)
{
ExecuteCommonCode(input);
}
protected override void ExecuteSpecificCode(object input)
{
var typedInput = (SomeType) input;
// ...execute whatever implementation-specific code here
}
}
public class BaseClass
{
protected void ExecuteCommonCode(object input)
{
// DoSomethingBefore(input);
ExecuteSpecificCode(input);
// DoSomethingAfter(input);
}
protected abstract void ExecuteSpecificCode(object input);
}
public interface IInitializer
{
void CallMeToInitialize(SomeType input);
}
// Get all IInitializers through dependency injection and call "CallMeToInitialize(new SomeType())" on each
Option two, use the template delegate pattern
How,does one should call an event declared by interface so that all the classes that has implemented that interface get notified??
For example in structure like this,
public delegate void myDel(int value);
interface IEventCaller{
event myDel myDelEventCall;
}
public Class One : IEventCaller {
public event myDel myDelEventCall;
}
public Class Two : IEventCaller {
public event myDel myDelEventCall;
}
I want both class One and Two to get notify and act as event gets called, I am feeling somewhere I am going wrong direction , is it possible to do?
Actually what you want doesn't involve events. Events would be used by an object implementing IEventCaller to notify some object holding a reference to that object of some change. To invoke something on the object implementing IEventCaller would just require a method, for example Hello();
First, you need code that informs all the objects that implement this interface. To make that possible, you somewhere need to store a list of instances that want to get notified.
One solution would be to create a class that manages that list. Let's say like this
private static List<IEventCaller> eventCallers = new List<IEventCaller>();
public static void AddEventCaller(IEventCaller c)
{
eventCallers.Add(c);
}
public static void RemoveEventCaller(IEventCaller c)
{
eventCallers.Remove(c);
}
public static IEventCaller[] EventCallers
{
get { return eventCallers.ToArray() }
}
Of course this code needs to be thread safe, etc. I'd put all this into a singleton to be globally available.
Then, all objects that implement IEventCallers need to register/unregister accordingly. Thus, I'd also have them Implement IDisposable so that in the constructor you can do
public EventCallable()
{
Singleton.Instance.AddEventCaller(this);
}
and in the Dispose method you can do this:
public void Dispose(bool disposing)
{
Singleton.Instance.RemoveEventCaller(this);
}
Now the code that should notify every instance could just do this:
public void NotifyAll()
{
foreach (IEventCaller caller in Singleton.Instance.EventCallers)
caller.Hello();
}
I think you might be looking at this the other one around.
With events, you want to have an object which is the publisher, which is responsible for publishing the event and saying "hey guys, something just occurred and you should know about it", and you have your subscribers, which are the guys who say "Yo dawg, let me know when that thing occurs, so i can act on it".
What you can do is have the object which is responsible for the event occurring implement your interface:
public class Publisher : IEventCaller
{
public event MyDel MyDeleteEvent;
public void OnDeleteOccured()
{
var myDeleteEvent = MyDeleteEvent;
if (myDeleteEvent != null)
{
MyDeleteEvent(1);
}
}
}
And then have your One and Two objects register to that event occurring, where they pass a method which signature matches the delegate type of MyDel:
public class SubscriberOne
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
public class SubscriberTwo
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
And the registration goes:
void Main()
{
var publisher = new Publisher();
var subscriberOne = new SubscriberOne();
var subscriberTwo = new SubscriberTwo();
publisher.MyDeleteEvent += subscriberOne.OnSomethingOccured;
publisher.MyDeleteEvent += subscriberTwo.OnSomethingOccured;
}
Let's say you have two different C# classes A and B that while not deriving from the same base class do share some of the same names for methods. For example, both classes have a connect and a disconnect method, as well as several others. I want to be able to write code once that will work with both types.
Here is a simplified example of what I would like to do:
public void make_connection(Object x)
{
x.connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
Of course, this does not compile as the Object class does not have a connect or disconnect method.
Is there a way to do this?
UPDATE. I should have made this clear from the start: I only have the DLLs for A and B and not the source.
You can use an interface to accomplish what you want to do.
interface IConnectable
{
void Connect();
void Disconnect();
}
Both A and B should implement IConnectable. Then use IConnectable instead of Object as the parameter type for your method and you should be all set.
public void MakeConnection(IConnectable connectable)
{
connectable.Connect();
// Do some more stuff...
connectable.Disconnect();
}
Edit: Since you don't have the source code, you have a couple of options:
Use Max's solution of using the dynamic keyword, (if you are using .NET 4.0)
Use Steve's solution of using casting and if/else statements
Create wrapper classes for A and B and have them implement the interface (or use common abstract base class for them)
For example:
class AWrapper : IConnectable
{
private A obj;
public AWrapper(A obj)
{
this.obj = obj;
}
public void Connect()
{
this.obj.Connect();
}
public void Disconnect()
{
this.obj.Disconnect();
}
// other methods as necessary
}
(BWrapper would be similar, just using B instead of A)
Then you could create the wrappers and pass them into MakeConnection. It's up to you how you want to do it. Depending on your situation, one method may be easier than the others.
This will work in C# 4:
public void make_connection(dynamic x)
{
x.connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
Try using an Interface rather.
Have a look at interface (C# Reference) and Interfaces (C# Programming Guide)
So something like
public interface IConnections
{
void connect();
void disconnect();
}
public class A : IConnections
{
public void connect()
{
//do something
}
public void disconnect()
{
//do something
}
}
public class B : IConnections
{
public void connect()
{
//do something
}
public void disconnect()
{
//do something
}
}
public void make_connection(IConnections x)
{
x.connect();
// Do some more stuff...
x.disconnect();
return;
}
There is a OOAD concept of 'Programe to an interface not to an implementation' which let's you avoid the chain of inheritance hierarchies
1- You can create a interfcae
interface IConnection
{
void Connect();
void Disconnect();
}
2- And let your classes implement this interface as shown below.
class A : IConnection
{
#region IConnection Members
public void Connect()
{
// your connect method implementation goes here.
}
public void Disconnect()
{
// your disconnect method implementation goes here.
}
#endregion
}
class B : IConnection
{
#region IConnection Members
public void Connect()
{
// your connect method implementation goes here.
}
public void Disconnect()
{
// your disconnect method implementation goes here.
}
#endregion
}
3- Once you done with the implementation than you can make your function accepting an argument of IConnection as shown below.
public void makeConnection(IConnection con)
{
con.Connect();
con.Disconnect();
}
4- And from your client code , you can pass the object of classes which implements IConnect Interface.
If the interface solution is not possible (e.g you don't have source code), another less effecient solution is to use reflection.
As others have said, re-factoring to use interfaces or using the dynamic approach are probably the most elegant ways.
If this is not possible you could cast the object to your types. I'd suggest using as and then checking that the cast worked, an unchecked cast would be dangerous if someone called this with a type that failed to cast.
E.g. If types A and B both have a method called DoSomething() then this will work...
public static void CallDoSomething(object o)
{
A aObject = o as A;
if (aObject != null)
{
aObject.DoSomething();
return;
}
B bObject = o as B;
if (bObject != null)
{
bObject.DoSomething();
return;
}
}
BUT this is pretty ugly to be honest... I'd really try and refactor to interfaces.
Either you will have to use an Interface (or Base class) as shown by Zach and astander, or you will have to case the object before using:
public void make_connection(Object x)
{
((A)x).connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
You could also use reflection to invoke the methods
What you want is called Duck Typing.
From Wikipedia:
Duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.
C# 4.0 allows this, as other have said, using the dynamic keyword
I have the following situation:
In a 3rd party library (can not be modified):
class A { public virtual void M() {} }
class B : A { public override void M() {} }
In my own code:
class C : B { public override void M() {} }
From C's implementation of method M I want to call A's (but not B's!!). Can I?
Any tricks accepted, reflection included. I tried reflection already, but using the MethodInfo that I get from typeof(A) still generates a virtual call (calling C's implementation with subsequent stack overflow).
Deriving C from A is out of the question due to the complexity of reimplementing B.
you can generate dynamic method to make proxy that use Call (not CallVirt) instruction
var x = new C();
var m = typeof (A).GetMethod("M");
var dm = new DynamicMethod("proxy", typeof (void), new [] {typeof(C)}, typeof (C));
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
var action = (Action<C>)dm.CreateDelegate(typeof (Action<C>));
action(x);
Quite old question but I had a similar problem recently.
desco's answer gave the crucial hint.
But the generated proxy delegate should be encapsulated in class C, can be static and initialized via static constructor so time consuming reflection will be required only once.
// -- in foreign assembly
class A { public virtual void M() { Console.WriteLine("A.M"); }}
class B : A {public override void M() { Console.WriteLine("B.M"); }}
//
// -- in own assembly
class C : B
{
private static Action<C> call_A_M;
public override void M() {
call_A_M(this);
Console.WriteLine("C.M");
}
static C()
{
var m = typeof(A).GetMethod("M");
var dm = new DynamicMethod("", typeof(void), new[] { typeof(C) }, typeof(C));
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
call_A_M = (Action<C>)dm.CreateDelegate(typeof(Action<C>));
}
}
But as Dan Bryant already mentioned: never ever use such dirty tricks in production code.
In my previous answer I missed the fact that A and B are in an external library and cannot be modified. In that case, I would suggest a different approach. Basically, if the design flaw is in B, you can’t use B. Subclass from A instead.
The unfortunate consequence of this, of course, is that you may need to reimplement some or all of the functionality in B. You may be able to copy the code from Reflector if necessary. I realise that this sounds undesirable, but I still think it is preferable to using unmodifiable code that has a known issue that causes you problems.
I’m afraid this is not possible directly the way you describe — the purpose of virtual methods is for the overriding to be transparent. So the only way to do this at all is via a workaround.
Let me try to whip one up, but please be aware that this is a hacky suggestion. If you really need this construct in your code, it may be an indication that your code has a fundamental design flaw somewhere else, so restructuring something might be more desirable than filling it with yet another design flaw. But anyway, here goes...
class A {
public virtual void M() { m_protected(); }
protected void m_protected() { /* code goes here */ }
}
class B {
public override void M() { /* code here, possibly invoking base.M() */ }
}
class C {
public override void M() { m_protected(); }
}
You cannot do that. You should probably design your class hierarchy differently, because it looks strange that C inherits from B, while behaving like A.
Anyway, it could make sense in your case. Then you should make another method in A which you will not override:
class A {
protected virtual void basicM() {}
public virtual void M() { basicM(); }
}
class C {
public override void M() { basicM(); }
}
BTW, if you name the method as I did in the example, then you should probably rethink the whole thing. If this hierarchy is justified, than basicM probably performs something that deserves to be a separate method with a different name, perhaps even a public method.
I have this kind of code:
public class Foo
{
public SomeHandler OnBar;
public virtual void Bar()
{
}
}
Foo is a base class and therefor other classes might inherit from it.
I would like the OnBar event to always be fired when Bar() is called even if it's not called explicitly inside Bar.
How can it be done?
A common pattern is to have a non-virtual method that will do what you want that calls a virtual method. Subclasses can override the inner method to change the functionality, but the public method can be non-virtual on always raise the event first.
public class Foo
{
public SomeHandler OnBar;
public void Bar()
{
if (OnBar != null)
{
OnBar(this, EventArgs.Empty);
}
BarImpl();
}
protected virtual void BarImpl()
{
}
}
Short answer: you can't. Not with what Microsoft gives you out of the box.
That said, take a look at "aspect oriented programming" in .NET. Google that, you might get something useful.
Added: The standard way would be to raise the event in the Bar() method and then require all derived classes to call the base implementation. But you can't enforce it.
first of all the code you provided will not compile.
virtual functions must have a body.
To ensure the event is fired you can do something like this.
public class Foo
{
public SomeHandler OnBar;
public void Bar()
{
OnBar(); (check for nulls)
ProtectedBar();
}
protected virtual ProtectedBar()
{
}
}
As Vilx- said, I guess the better way to do this kind of stuff is to use Aspect Oriented Programming.
This would help you with the "entangled code" (ie. calling an event in a method that shouldn't have this responsibility) and "scattered code" (ie. calling the same event in a lot of methods, duplicating your code) problems.
You should take a look at postsharp, it has a free community edition.