So I have a confusion about how to pass a method with a specific signature to a form that then can invoke said method with its own parameters and evaluate the return value.
The problem, the more I read about delegates, events, event-handlers, subscribing and Func and Actions .. the more I am confused. (I have tried lots of them, modified lots of them and non worked, but I suppose thats because I don't get how they work)
Example of what I want to do:
public class WorkingStatic {
public static SetUpForm() {
SomeForm tmp_Form = new SomeForm(StaticMethod);
/*somehow pass the method to the form so that it can invoke it*/
tmp_Form.Show();
}
public static int StaticMethod(int p_Int) {
// do whatever..
return p_Int;
}
}
That is just a class with a method that does something, important is the method takes an int as parameter and returns an int.
Now comes the Form as I would like it to work .. so code is not working:
public partial class SomeForm : Form {
private Method m_Method;
public SomeForm(/*here I pass a method*/Method p_Method) {
InitializeComponent();
m_Method = p_Method;
}
public void SomeMethodThatGetsCalledByAButton() {
m_Method.Invoke(/*params*/ 1); /*would return 1*/
}
}
None of this works 'what surprise', and because I am getting kind of frustrated about it I thought I'd ask you guys.
Thanks in advance!
-RmOL
Since the answer I marked got deleted I'll post what worked for me.
Thanks to #Fabio for supplying the solution. (as a comment)
Func</*input types here with ',' in between*/, /*output type here*/>
can be handled like just any other type. (When passing the method do not put normal brackets or any other arguments concerning that method after it)
Example like shown in the question would then look like this:
public class WorkingStatic {
public static SetUpForm() {
SomeForm tmp_Form = new SomeForm(Func<int, int>(StaticMethod));
/*pass the method to the form so that it can invoke it*/
tmp_Form.Show();
}
public static int StaticMethod(int p_Int) {
// do whatever..
return p_Int;
}
}
public partial class SomeForm : Form {
private Func<int, int> m_Method;
public SomeForm(Func<int, int> p_Method) {
InitializeComponent();
m_Method = p_Method;
}
public void SomeMethodThatGetsCalledByAButton() {
m_Method(/*params*/ 1); /*would return 1*/
}
}
Related
I have the following Structs which hold an Action and a T paramater:
public struct CallbackInfo<T>
{
public readonly Action<T> callback;
public readonly T param;
}
What i am trying to do is store a list of these callbackInfo structs to of course, callback at some point in time.
Lets say that I store these structs as follows:
public class CallbacksSystem<T>
{
List<CallbackInfo<T>> callbacks;
public void AddCallback<T>(T callback)
{
callbacks.Add(callback);
}
public void RunCallbacks()
{
foreach(CallbackInfo<T> info in callbacks) info.callback(info.param);
}
}
However, this would mean that I would need to have a new CallbackSystem for each different T i need to submit callbacks for.
Is there a way in c# to have the list stored as a wildcard and get the concrete type at runtime to run the callback Action?
As other have alluded to, your problem may be resolved with Events
If events are not solving your entire problem, I'm sorry to report that wildcard generics do not exist in this case. However, perhaps a lambda-driven approach would suffice.
Proposal 1
Here, the code binds your state and your callback together by capturing them in a lambda. This lambda is then saved in the list like an anonymous function.
public class CallbacksSystem
{
private List<Action> Callbacks { get; } = new List<Action>();
public void AddCallback<T>(Action<T> callback, T parameter) // Or with your struct
{
Callbacks.Add(() => callback(parameter));
}
public void RunCallbacks()
{
foreach(var callback in Callbacks) callback();
}
}
Proposal 2
If you have multiple instances of this pattern where you locally have a single function which needs to be called multiple times with accumulated parameters, you could instead create a class like this:
public class DeferredCallback<T>
{
public DeferredCallback(Action<T> callback)
{
Callback = callback;
}
private Action<T> Callback { get; }
private List<T> Parameters { get; } = new List<T>();
public void AddDeferredCall(T parameter)
{
Parameters.Add(parameter);
}
public void RunCallbacks()
{
foreach(var parameter in Parameters) Callback(parameter);
}
}
You would then instantiate this class once for each callback you have. What fits best would all depend on how the rest of the problem (and the system) looks like, but these examples will hopefully put you on the right path(?).
Alright, so I have a class. In that class I have the following property:
private Func<object, OutputEventArgs> _outputMethod = null;
public Func<object, OutputEventArgs> OutputMethod
{
get { return _outputMethod; }
set { _outputMethod = value; }
}
I want the class to be able to invoke this method which is going to allow it to send outputs (error messages and the like) to somewhere of my choosing.
That seems to work alright, but the issue comes when I want to assign that property.
I have another class called OutputHandler which looks like this:
public static class OutputHandler
{
public static void HandleOutput(OutputEventArgs e)
{
}
}
I'm aware I could just call that method directly from the class in question, but I want to enforce some kind of separation of concerns.
So my assignment is like this (c1 being an instance of the class with the Func in it):
c1.OutputMethod = ????
I've tried a few things, but none of them work. I've also looked up and down this site and come up with nothing so far.
Like others have mentioned, you can change your OutputMethod to an Action instead of a Func, or you can change:
public static void HandleOutput(OutputEventArgs e)
{
}
to
public static object HandleOutput(OutputEventArgs e)
{
}
I have a class that takes an Action for the constructor, let's say class A.
public class A
{
public A(Action action) {...}
}
and I instantiate it.
class Program
{
void Main()
{
A a = new A(() => { DoSomethingWith(x); });
}
}
The question is: How can I refer to 'a' in my action? In other words, how can I replace 'x' with 'a'?
I tried 'this' keyword but it refers to Program.
By the way, I can not use other inputs for my constructor, because the actions are very random in this project.
a isn't fully constructed until the constructor runs. That means that it isn't available inside the Action delegate at that point. If you want, you can create a different type of Action delegate:
public class A
{
public A(Action<A> myAction)
{
myAction(this);
}
}
public class B
{
public B()
{
var myA = new A((a) => { DoSomethingWithA(a); });
}
public void DoSomethingWithA(A a)
{
}
}
That allows it to be called with itself as an argument. The straight Action won't work though because you can't capture a before it is fully constructed.
This does seem to be an X-Y problem though, and I would avoid doing this if possible because it is difficult to tell if DoSomething is using a fully initialized A before the action is called, which can leave your object in an undetermined state. There are uses, just be careful.
As pointed out, you can't assign the action in the constructor because a has not been constructed yet. Don't confuse assigning the action with running it. You probably want to run the action at a different time to when you create a.
Without necessarily condoning the approach (it's a bit ugly and there's probably a better way to achieve your ends), you could do something like this instead:
public class A
{
Action<A> MyAction
public A(Action<A> action)
{
MyAction = action;
}
public void DoMyAction()
{
MyAction(this);
}
}
class Program
{
void Main()
{
var a = new A((x) => { DoSomethingWith(x); });
a.DoMyAction();
}
}
I have an object that can be of type AudioRequest or VideoRequest. Both classes inherit from Request. I have this class:
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
I want to be able to call DoThings.HandleRequest(r) where r can be either a VideoRequest or AudioRequest and have it call the correct one. Is that possible? I have no control over the *Request classes, so I can't do anything to them. I do have control of the DoThings class and the code that calls HandleRequest. This is the code that calls it, it is WebAPI:
public Response Post(Request input)
{
return DoThings.HandleRequest(input);
}
The code above gives the error Argument 1: cannot convert from 'Request' to 'AudioRequest'.
The original code that I was cleaning up had this:
if (input.GetType() == typeof(AudioRequest))
{
var audioRequest = (AudioRequest)input;
DoThings.HandleRequest(audioRequest);
}
else if (input.GetType() == typeof(VideoRequest))
{
var videoRequest = (VideoRequest)input;
DoThings.HandleRequest(videoRequest);
}
But I figured there was a cleaner way to do this.
Based on the information you've provided so far, your question appears to be a duplicate of How to call a function dynamically based on an object type. I agree with the answer, that the fact that you want to do this suggests you should rethink the design. But, you can use dynamic to accomplish what you want.
Here's a simple console program that demonstrates the basic idea:
class Program
{
static void Main(string[] args)
{
A b = new B(), c = new C();
M(b);
M(c);
}
static void M(A a)
{
WriteLine("M(A)");
M((dynamic)a);
}
static void M(B b)
{
WriteLine("M(B)");
}
static void M(C c)
{
WriteLine("M(C)");
}
}
class A { }
class B : A { }
class C : A { }
The output is:
M(A)
M(B)
M(A)
M(C)
As you can see, in each case the M(A) method is called first, and then the appropriate M(B) or M(C) overload is called from M(A).
In your own example, this could look something like this:
public static DoThings
{
public static void HandleRequest(Request r)
{
// Dynamic dispatch to actual method:
HandleRequest((dynamic)r);
}
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
Note that dynamic does incur a run-time cost, particularly the first time a method is called with a given run-time type. But depending on the frequency and complexity of these "requests", using dynamic could be the cleanest way out of the current situation.
C# will call the appropriate function that matches the arguments and their types.
That being said, both of your functions accept AudioRequest, I believe one of those should accept a VideoRequest.
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
If for some reason you must have two different functions that take only AudioRequest you can differentiate between two function with an extra parameter
public static class DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(AudioRequest r, bool UseAlternativeMethod)
{
// Do other things.
}
}
Simply having a second parameter will call the second method regardless of it's value.
This isn't a best practices solution as you'd rather discriminate between them by accurately renaming the method name to be accurate but in practice you don't always have a choice.
I have a function like this:
public static int WriteLog(string messageCode, params string[] parameters)
{ ///do some operation here }
Based on the first argument(messageCode) the other arguments names change.
Now i prepared this function for developers, and I want to know whether the is any way to load the name of other arguments, when they type messageCode and after that they can see the name of the next arguments.
For example if they type "first" for messageCode and call the function, Visual Studio shows them something like this:
When they type "second" for messageCode and call the function, Visual Studio shows something like this:
You can't do that. There's simply no way of representing that in C# with your current approach.
What you could do is have a bunch of classes each with a WriteLog method, in a sort sort of pattern which emulates Java enums to some extent. So something like this:
public class LogMessage
{
public static FirstMessage First { get { return FirstMessage.Instance; } }
public static SecondMessage Second { get { return SecondMessage.Instance; } }
// Prevent instantiation outside this class's program text.
private LogMessage() {}
protected void LogImpl(string code, params string[] parameters)
{
...
}
// You may have some common public methods here, potentially...
public sealed class FirstMessage : LogMessage
{
internal readonly static FirstMessage Instance = new FirstMessage();
private FirstMessage() {}
public void WriteLog(string userName, string logSource, int targetLocation)
{
// Call to LogImpl here
}
}
// Ditto for SecondMessage
}
Then the calling code would use:
// Intellisense will prompt here...
LogMessage.First.WriteLog(...);