Delegate a method call, to another method - c#

I am not sure if what I am looking for is even possible, but I wonder if there is a way to delegate a method, when it is called, to another method. Let's say I have a declared object Receiver with a public method OnReceived(string param), inside a class ReceiverMiddleMan. When this method is called on Receiver, I would like to pass the parameters of this method to a method OnReceivedInMiddleMan somehow, not necessarily in the way as is shown in the code. Why? Because I would like to know if the data in Receiver.OnReceived can be got directly, without for instance inheriting from Receiver to access the method. The Receiver class, used here as an example, is in real life a Third party library which I cannot modify with events and such. The only access I have is the public method.
class Receiver
{
public void OnReceived(string param)
{
//do something
}
}
class ReceiverMiddleMan
{
Receiver receiver = new Receiver();
Listen(receiver.OnReceived);
public void Listen(Method method)
{
OnReceivedInMiddleMan(method.param);
}
public void OnReceivedInMiddleMan(string param)
{
//do something
}
}

Related

Is it possible create a custom method attribute to control the method signature or the method's parameters?

I would like to control in a class the signature of certain methods so that it throws a compilation error if a method does not have the signature I want.
I have thought do it creating a custom attribute, something like this:
public class CustomAttributeForMethodWithStringParameterFirstAttribute : Attribute
{
}
public class MyClass
{
[CustomAttributeForMethodWithStringParameterFirst]
public void Method1 (string p)
{
}
[CustomAttributeForMethodWithStringParameterFirst]
public void Method2 () // <--- I wish a compile error
{
}
}
But... Now I do not know how to continue.
Is it possible do this via attributes?
Thanks in advance.
If not, is there any way to do it?
EDIT
Sorry, I have simplified my scenario to expone the concrete problem.
I'm writting the interface for a WCF service and I wish implement this attributes in the interface. Certain methods must have one string parameters in first position for custom operations.
I've developed a custom attribute to do something with this first parameter before methods calls of my service.
public interface MyInterface
{
[CustomAttributeForMethodWithStringParameterFirst]
void Method1 (string p);
[CustomAttributeForMethodWithStringParameterFirst]
void Method2 (); // <--- I wish a compile error
}

Design concept (pattern?) for method call in c#?

I would like to create a structure where I call a method and this method parameter should be only available only from an instanced class.
What I exactly mean..., I have a class which contains functions like:
public class Functions
{
public Request GetId(int item)
{
//return instanced request
}
public Request SetId(int item)
{
//return instanced request
}
}
I have an invoker class, which has a method, called Invoke(Request request).
I would like to use Functions class as the parameter of this method, but accepted parameters can only be come from this class.
Actually I do this to create an instance from the functions class inside the class of the Invoke method and looks like this:
Functions Requests = new Functions();
...so when I would like to call the Invoke method, it looks like this:
Invoke(Requests.GetId(1));
But is there any way to solve, that I can only Invoke Requests from the instanced class, like:
Invoke(GetId(1));
Maybe I think on a wrong way but hopefully, it's clear what I would like to reach. (Seperate Functions from the Invoker class but keep the relation between them).
Thank you!
Why not to make class and methods static
public static class Functions
{
public static Request GetId(int item)
{
//return instanced request
}
public static Request SetId(int item)
{
//return instanced request
}
}
and then
using static Functions;
you will be able to use this syntex then:
Invoke(GetId(1));
But this is not good practice.

How to get the object from a MethodBase class instance

I have a module (Fody.MethodTimer) that I can extend my classes with attributes. When my class'es method gets executed it, invokes a static method (in another class)
public class CommandBase
{
[Time]
public bool test()
{
return true;
}
}
public static class MethodTimeLogger
{
public static void Log(MethodBase methodBase, long milliseconds)
{
//Do some logging here
}
}
Basically, after the method is call of test is complete, the Log method gets executed. As you can see, it get a MethodBase argument and has all that is needed do decribe the method that invoked this method call.
my Question is, If it is possible to get the object that invoked the Log method Call, out of The .NET MethodBase class instance.
No. MethodBase is extracted from a type, not an instance. You will need to pass the instance in as a parameter if you want to invoke methods on it.
Even if you could, how would you know what parameter values to use when calling the method?
This is why all built-in event handlers have an object sender parameter - so you know which object triggered the event.

Pattern for allowing client delegate to override default behavior

I have a C# class that has some functionality that I'd like to allow a client of the class to override. Specifically I'd like the following:
If the client does nothing, they get our default behavior
The client can override the behavior and cause our default behavior to not be called.
The client can override the behavior and cause our default behavior to be called as a pre/post/middle operation.
My current thinking is to:
Expose an event that the client would subscribe to if they wanted to override the behavior.
Expose a method with the default behavior (that matches the signature of the event):
void DefaultBehavior()
Whenever we attempt to fire the event, if the delegate is null, we call our default behavior method, otherwise, we call the delegate of the event:
if (eventDelegate == null)
DefaultBehavior();
else
eventDelegate();
When the client overrides the behavior they can optionally call our DefaultBehavior method to get the desired behavior.
Do you think this approach will be intuitive enough from the client's perspective? Or can you suggest any alternatives that might be better?
Well, if you want your client to override some behavior, why not create a virtual function, an let the client actually override it?
It's the straightforward way of accomplishing this. No need to reinvent the wheel.
If I understand your question, by client you mean some code calling your class, and not overriding your class, assuming you need to do it this way (I agree with #zmbq answer if you can do it that way):
You can make your method have 2 overloads, one with no parameters and another receiving a Action object
public void methodName()
public void methodName(Action delegate)
then in the body of methodName() you will call the other method with defaultAction
public void methodName()
{
methodName(DefaultBehavior);
}
finally in the second method you just call the delegate passed as parameter, without caring if it's the default or not
public void methodName(Action delegate)
{
delegate();
}
the client of your class will see this two overloads and decide wether to use the default or give a custom behavior
EDIT:
Ok, last try :), according to your last comment would it work for you to have an instance field
private Action behaviorDelegate = DefaultBehavior;
Anywhere in your class you can assign to behaviorDelegate a different behavior, and then you don't need an if statement since the behavior will always be in delegate variable whether it is the default or not. It is not a big change but it seems cleaner to me.
You could (perhaps?) also do it without events:
Declaration:
public class DemoClass
{
public delegate string MyDelegate(string testValue);
public static MyDelegate DefaultBehavior
{
get
{
return testValue =>
{
return String.Concat(testValue,
", now with 99% more exclamation points!!!!!!!!");
};
}
}
public MyDelegate ModifyString = testValue =>
{
return DemoClass.DefaultBehavior(testValue);
};
}
Use:
// first, default:
DemoClass demoObject = new DemoClass();
Console.WriteLine(demoObject.ModifyString("My test string"));
// now, pure "override":
demoObject.ModifyString = testVal =>
{ return String.Concat(testVal, ", this time with question marks????");
};
Console.WriteLine(demoObject.ModifyString("Second test string"));
// finally, define a delegate that overrides and calls default:
DemoClass.MyDelegate combined = testVal =>
{ return String.Concat(DemoClass.DefaultBehavior(testVal),
", now we're really tricky");
};
demoObject.ModifyString = combined;
Console.WriteLine(demoObject.ModifyString("Third test string"));
Output:
My test string, now with 99% more exclamation points!!!!!!!!
Second test string, this time with question marks????
Third test string, now with 99% more exclamation points!!!!!!!!, now we're really tricky
Just use a virtual method:
public class BaseClass {
public virtual void Something() {
Console.WriteLine("base functionality");
}
}
public class Sub1 : BaseClass {
public override void Something() {
// do whatever you want here
base.Something(); // don't call it at all if you like
// do whatever you want here
}
}

Use class method from another class

I am trying to use a method inside class, from another class.
namespace Crystal.Utilities
{
public class Logging
{
public static void Log()
{
//dostuff
Crystal.MainForm.general_log_add_item("Hello World");
}
}
}
namespace Crystal
{
public partial class MainForm : Form
{
public void general_log_add_item(string msg)
{
listBox1.Items.Add(msg);
}
}
}
I want to be able to call Crystal.Utilities.Logging.Log() from anywhere, and that to be able to call Crystal.MainForm.general_log_add_item() . But It doesn't let me, because if I put it as public, then I can't see it, if it's static then It can't interact with my listbox.
This is a wrong approach. Your class should not call into the UI, as the UI could change. The class should not know nor care about the UI. Instead, the class could expose an event that the form could subscribe to, and update based upon the information contained within the event's arguments.
Here's a hastily thrown together example.
class Program
{
static void Main()
{
Logger.OnLogging += Logger_OnLogging;
Logger.Log();
Logger.OnLogging -= Logger_OnLogging;
}
static void Logger_OnLogging(LoggingEventArgs e)
{
Trace.WriteLine(e.Message);
}
}
public class Logger
{
public delegate void LoggingEventHandler(LoggingEventArgs e);
public static event LoggingEventHandler OnLogging;
public static void Log()
{
// do stuff
RaiseLoggingEvent("Data logged");
}
protected static void RaiseLoggingEvent(string message)
{
if (OnLogging != null)
OnLogging(new LoggingEventArgs(message));
}
}
public class LoggingEventArgs : EventArgs
{
public LoggingEventArgs(string message)
{
this.Message = message;
}
public string Message { get; private set; }
}
Instead of implementing it as a static method, try implementing as a singleton. It's a common trick to make an instance global in scope, and restrict to one instance, without making everything static (and thus unable to be used as an instance).
You have to understand that the window is not static, there is one instance of him, thats why the method cant be static,
you can use
Application.Windows to reach this instance and call the add method.
or you can register the window in his constructor on another class that will mediate the Logging and the window.
If you don't understand tell me and I'll try to be more clear
When you declare a method as "static" you're saying that it's not dependent upon a specific instance of the class it's in.
For example if you have a class named "chair" and you want to count how many chairs there are, you'll do that with a static field, and a static method to return that field's value.
The count of all chairs is not related to a specific chair.
In your case you want to add a static method to add an item to a specific instance of a Form. That's impossible and doesn't make sense.
If you want to add an item to a listBox, it must be through a public method.
So basically what I'm saying is - rethink what you're trying to do, there's a good explanation as to why you're not succeeding in doing that.

Categories