How to define a new class that inherits from Delegate - c#

is there anyway to do something similar to what ive got bellow.
What im trying to do is to invoke a list of delegates at a specific point in time and keep track of them, and for the sake of keeping code clean, keep the delegates to be invoked in a list of some sort.
public interface IServiceStatusDelegate
{
object DynamicInvoke(object[] args)
}
public class ServiceStatusDelegate
: Delegate, IServiceStatusDelegate
{
}
public class MyServiceStatusCheckedDelegate
: ServiceStatusDelgate
{
}
public class MyServiceStatusChangedDelegate
: ServiceStatusDelgate
{
}
public class MyClass
{
public ServiceStatusDelgate[] listOfDelegatesToInvoke;
public void InvokeRequiredDelegates()
{
foreach(ServiceStatusDelegate delegateToInvoke in this.listOfDelegatesToInvoke)
delegateToInvoke.DynamicInvoke(new object[]{this, DateTime.Now});
}
}

You don't need a list of delegates... any delegate you create in c# is going to be multicast, so all you need is any delegate, and you can combine them with +. Just invoke it and all targets will be reached. For example:
Action target = null;
...
target += Method1;
...
target += Method2;
...
if(target != null) target(); // calls Method1 and Method2
This could (although it isn't necessary for it to stand) be implemented via an event which will make the convention very obvious the caller.

Related

C# Call function from another class

I think my question is best descirbed by a code snippet:
class A
{
public void FunctionToBeCalled();
}
class B
{
public void FunctionToBeCalledAfter();
}
Now, after a FunctionToBeCalledAfter() call, FunctionToBeCalled() needs to "know" it must be called. B cannot have an A member, but A can have a B member. Is there any way this can be implemented in C#?
Why i need this:
Class A is Application level on OSI stack. Classes B and C(unmentioned before) are Transport Level. C makes calls to FunctionToBeCalledAfter, and after this FunctionToBeCalled needs to be called. But sincer A is a higher level, B and C cannot depend(have a member A), i don't know how to call FunctionToBeCalled.
I see 2 ways to accomplish this, one easier but (arguably) less elegant, one a little more involved but (arguably) more elegant
The less elegant solution: Singleton
A Singleton pattern enforces that there can only ever be one instance of a class at any given time, this seems to line up with your description of A (which from here on out I'll call Foo, and I'll be calling B Bar). So let's implement it:
public class Foo
{
private static Foo _instance;
public static Foo Instance => _instance ?? (_instance = new Foo());
// Private constructor so no one else can instantiate Foo
private Foo() { }
public void FunctionToBeCalled() { /* your code here */ }
}
public class Bar
{
public void FunctionToBeCalledAfter()
{
// Your existing code here
Foo.Instance.FunctionToBeCalled();
}
}
Now, the problem here is if your requirements ever change and you need multiple Foos, that'll be quite a refactor to implement it. Another (larger) downside is that we explicitly reference (i.e depend on) Foo, which isn't great and a problem if Bar is inside a project/ library that cannot directly reference Foo. Luckily solution 2 fixes those problems:
The more elegant solution: Events
public class Foo
{
// We don't need Foo to be a singleton anymore
public void FunctionToBeCalled() { /* Your code here */ }
}
public class Bar
{
public delegate void FunctionToBeCalledAfterEventHandler();
public event FunctionToBecalledAfterEventHandler FunctionToBeCalledAfterEvent;
public void FunctionToBeCalledAfter()
{
// Your existing code here
OnFunctionToBeCalledAfterEvent(); // Fire the event
}
private void OnFunctionToBeCalledAfterEvent()
{
FunctionToBeCalledEvent?.Invoke();
}
}
Now, everywhere where you're creating an instance of Bar you need to have a reference to Foo and subscribe to the event like so:
// foo = instance of class Foo
var bar = new Bar();
// The compiler is smart enough to find out that 'FunctionToBeCalledAfterEvent'
// has the same signature as 'FunctionToBeCalledAfterEvent' and can call it directly
// If this just so happens to not be case, see second way to subscribe to events
bar.FunctionToBeCalledAfterEvent += foo.FunctionToBeCalled;
// Or
bar.FunctionToBeCalledAfterEvent += () => foo.FunctionToBeCalled();
Events are great
Class B can have an event that other parties can handle. At the end of B.FunctionToBeCalledAfter this event would be invoked. Anyone who registered for this event would then be notified. Usual boilerplate code involves one virtual method that invokes one event. It's the standard way of adding events. If there is no need for additional data in the event then EventArgs is used. If additional data is needed then you could replace EventArgs with EventArgs<YourData>, or as an alternative, introduce a class XxxArgs derived from EventArgs with this additional data.
Class B
{
public event EventHandler FinishedFunctionToBeCalledAfter;
protected virtual void OnFinishedFunctionToBeCalledAfter(EventArgs e)
{
EventHandler handler = FinishedFunctionToBeCalledAfter;
handler?.Invoke(this, e);
}
public void FunctionToBeCalledAfter()
{
...
OnFinishedFunctionToBeCalledAfter(EventArgs.Empty);
}
}
Now when class A gets a hold of an object of class B it would add its event handler to it:
class A
{
public void FunctionToBeCalled();
public void FinishedFunctionToBeCalledAfter(object source, EventArgs e);
public void IntroduceObject(B b)
{
b.FinishedFunctionToBeCalledAfter += FinishedFunctionToBeCalledAfter;
}
}
When this object b of class B should end its life class A must know about it so that it can remove its event handler:
b.FinishedFunctionToBeCalledAfter -= FinishedFunctionToBeCalledAfter;

passing a method as a constructor's parameter

While I was looking at some c# code I found a new class declaration which had passed a method as a constructor’s parameter.This is my first time I have seen something like this and it has no meaning for me .Although the whole application works fine I am still interested to know what is the main idea behind the scene.
var c = new List<TheClass>
{
new TheClass(TheMethod);
}
private void TheMethod()
{
//do somthing
}
I guess the TheClass constructor accepts an Action delegate:
public class TheClass
{
private readonly Action _action;
public TheClass(Action action)
{
_action = action;
}
}
This way TheClass can execute the provided action at a later time, and more than once.
For example:
public void DoAction()
{
_action();
}
You could also do:
var theClass = new TheClass(() => TheMethod());
There are many reasons that you might want to pass a method into the constructor of a class.
One of the most important is for so-called Dependency Injection, where want to inject a dependency into a class.
Suppose that a class needs to create an object. Normally, that class would do something like var item = new MyConcreteClass();.
However, that creates a strong dependency between the class creating the object and MyConcreteClass. This can make it harder to unit test or change implementations.
To circumvent this problem, you can do this:
Extract from MyConcreteClass an interface (say IMyInterface) which contains all the things you need to use from inside the class being written.
Pass to the class constructor a Func method which creates and returns a concrete class as IMyInterface.
Inside the class being written, call that Func to create the object rather than creating it directly using new.
The Func is therefore acting as a factory.
Code might look like this:
using System;
namespace Spacelabs.WcfDuplexDemo.Client
{
static class Program
{
static void Main()
{
var myClass = new MyClass(() => new MyConcreteClass());
myClass.DoSomething();
}
}
public interface IMyInterface
{
string MyMethod(int param);
}
public sealed class MyConcreteClass : IMyInterface
{
public string MyMethod(int param)
{
return param.ToString();
}
}
public sealed class MyClass
{
private readonly Func<IMyInterface> createMyInterface;
public MyClass(Func<IMyInterface> createMyInterface)
{
this.createMyInterface = createMyInterface;
}
public void DoSomething()
{
// Instead of var item = new MyConcreteClass(), we do the following:
var item = createMyInterface();
Console.WriteLine(item.MyMethod(12345));
}
}
The main idea is to defer execution of the method and control when it gets executed.
One use case for this is passing a method that creates and object so that the class controls when the object is created and it can control how many times it is created.
Are you unclear of why a method is being passed as an argument or specificly as an argument in a constructor?
CodeCaster already spoke short about Action delegates and if you're interested in storing methods in delegates like Action, I suggest you read up on Delegates here
I'd like to provide a short example of a class that contains an Action delegate: RelayCommand -> I've illustrated the use of this delegate with the MVVM pattern below:
class ViewModelDefault : INotifyPropertyChanged
{
public string TextProperty { get; set;}
public ICommand ButtonProperty
{
get {
RelayCommand relayCommand = new RelayCommand(ExecuteCommand);
return relayCommand;
}
}
private void ExecuteCommand()
{
HandlerClass handler = new HandlerClass();
handler.SaveTextInTextfile(TextboxProperty);
}
...
}
In the MVVM pattern, your main focus is to seperate data, logic and view, which is why using Delegate is perfect in this scenario.
You'd normally want to bind a property such as a string from the ViewModel to a View UI Element such as a TextBox.
Making use of delegates, allows you to bind a method (which would otherwise not be bindable to a UI element) through an Action property.
In the example above, the method ExecuteCommand is stored in an action field inside the RelayCommand object. This is bindable to a UI element, and will execute the method once it's requested.

Error when doing simple event\delegate calls when generic class is involved

The following classes
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage) { }
}
Throws the error:
InvalidCastException: Cannot cast from source type to destination type
When I try to add a listener to the event as seen in the example above.
The call to SetupWithPagedList is correctly parametrized:
obj.SetupWithPagedList<Monster>(pagedMonstersList)
I have done events and delegates a lot before, the only difference here is that there is a <T> involved in this class. Has anyone had issues doing events and delegates with templates?
I think your problem in this case is with, the instances. The first question I made when I saw your PagedItemListCode was, why SetupWithPagedList is not an static method, and I checked that you are calling the NotifyPageChanged method in the instance of the class. I do not know the logic behind the problem, but maybe the right way is like this:
public static void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(list.NotifyPageChanged);
}
Note that the instance of the class maybe is not the same instance of the object that is passed to the SetupWithPagedList method. Maybe the class is PagedItemList<A> and the method parameter is PagedItemList<Monster>. Maybe the class do not need to be generic. Check it.
EDIT
I tried your code and works perfect:
var p = new PagedItemList<int>();
var sc = new SomeClass();
sc.SetupWithPagedList(p);
p.RaisPageChanged(5);
...
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
public void RaisPageChanged(int page)
{
if (PageChangedEvent != null)
PageChangedEvent(page);
}
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage)
{
Debug.WriteLine("Page: ",newPage);
}
}
Check it, maybe is something else.

C# registering for an event via constructor

I've got a class which is generating an event.
Normally I register with this.obj.testEvent += new oClass.LogHandler(handleIt);
The class oClass has a property containing an instance of another class.
public class oClass
{
public qClass qclassobj;
}
And qClass has a property containing an instance of pClass etc.
When I create an instance of oClass, the other classes are also created.
Is it possible to register recursively to all the events (which do have to same name and attributes) by passing a parameter via the constructor or something like that?
So that ever ytime the testEvent is generated in one of the classes the handleIt function is called.
I hope you understand my question, any help appreciated :)
KR
If I understand your question correctly, you can pass it in using a delegate:
class RootClass
{
public event EventHandler<ResolveEventArgs> Resolve;
public RootClass() { }
public RootClass(EventHandler<ResolveEventArgs> resolve)
{
if (resolve != null)
Resolve += resolve;
}
}
class InheritedClass : RootClass
{
public InheritedClass() { }
public InheritedClass(EventHandler<ResolveEventArgs> resolve)
: base(resolve) // Is this what you are looking for?
{
}
}

Events returning values as methods, is it correct?

In my app, I wanted to let class B get some information from class A but as A instantionates B, B has no reference to A (intentionally).
I have never used events for that purpose so I am not sure whether its correct, but it works:
class A
{
public delegate bool GetFromB();
public event GetFromB GetDataFromB;
...
//get data from B without having an access to it
bool Result=GetDataFromB();
}
class B
{
A a=new A();
A.GetDataFromB=new A.GetFromB(DO_THAT);
public bool DO_THAT()
{
...
return true; //and that is it, it will return to event caller
}
}
It'll certainly work, and that approach is used in a few places in the core framework - AssemblyResolve etc. Alternative approaches here:
if it is used by a method, pass it into the method as a callback delegate. Same approach, but simply not exposed as an event
ditto, but with an interface
but it'll work that way. It isn't unheard of. Code tweaks, though:
A a=new A();
a.GetDataFromB=+new A.GetFromB(DO_THAT);
you subscribe on the instance (unless it is static), and need +=, not =.
Also: consider using Func<bool> rather than declaring your own delegate type.
Don't do that. Events implies that multiple listeners can be used, and it looks like you are not handling return values from multiple listeners. You can do that by traversing myevent.GetInvocationList() and invoke each listener separately.
Use a simple delegate instead:
class A
{
public delegate bool GetFromB();
public GetFromB GetDataFromB { get; set; }
}
The other standard way is to have event arguments that provide a property for return value.
class MyEventArgs : EventArgs
{
public bool ReturnValue {get; set; }
// and something more here.
}
public class A
{
public event EventHandler<MyEventArgs> MyEvent;
}
As you wrote, A currently instanciates B so, you should not change this by creating an instance of A in B.
If B needs several different data from A, you can let A realize some IBNeededData interface. If B needs only one call on A, the straight forward solution would be a callback method.
Edit
Here's a sample for the callback. (Hope you are fine with the lambda expression to provide the data from A.)
[TestClass]
public class UnitTest1 {
class A {
public void DoWork() {
B b = new B();
//b.GetData = () => "Some data";
Func<string> callback = new Func<string>(this.GetBData);
b.GetData = callback;
b.DoBWork();
}
private string GetBData() {
return "Some data";
}
}
class B {
public Func<string> GetData { get; set; }
public void DoBWork() {
string data = GetData();
Console.WriteLine("Working with {0}", data);
}
}
[TestMethod]
public void TestMethod1() {
A a = new A();
a.DoWork();
}
}

Categories

Resources