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();
}
}
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(?).
Sorry its a bit vague perhaps but its been bugging me for weeks. I find each project I tackle I end up making what I think is a design mistake and am pretty sure theres a bettwe way.
When defining a class thats serialized from an event source like a sinple json doc definition. Lets call it keys class with various defined integers, bools and strings. i have multiple methods that make use of this and i find that i constantly need to paas this class as an object by means of an overload. So method a calls methods b, method b doesnt need these objects but it calls method c which does... In doing this bad practice im passing these 'keys' objects to method b for the sole purpose of method c accessibility.
Im probably missing one major OOP fundamental :) any guidance or reading would be appreciated as im googled out!!
public class Keys
{
public child Detail { get; set; }
}
public class child
{
public string instance { get; set; }
}
//my main entry point
public void FunctionHandler(Keys input, ILambdaContext context)
{
methodA(input)
}
static void methodA(Keys input)
{
//some-other logic or test that doesn't need Keys object/class if (foo==bar) {proceed=true;}
string foo = methodB(input)
}
static string methodB(Keys input)
{
//here i need Keys do do stuff and I return a string in this example
}
What you do is not necessarily bad or wrong. Remember that in C# what you actually pass are references, not objects proper, so the overhead of parameter passing is really small.
The main downside of long call chains is that the program logic is perhaps more complicated than it needs to be, with the usual maintainability issues.
Sometimes you can use the C# type system to let the compiler or the run time choose the proper function.
The compiler is employed when you overload method() for two different types instead of defining methodA() and methodB(). But they are distinguished by the parameter type, so you need different Key types which may be (but don't have to be) related:
public class KeyA {/*...*/}
public class KeyB {/*...*/}
void method(KeyA kA) { /* do something with kA */ }
void method(KeyB kB) { /* do something with kB */ }
This is of limited benefit; that the functions have the same name is just syntactic sugar which makes it clear that they serve the same purpose.
The other, perhaps more elegant and versatile technique is to create an inheritance hierarchy of Keys which each "know" what a method should do.
You'll need a base class with a virtual method which will be overridden by the inheriting classes. Often the base is an interface just declaring that there is some method(), and the various implementing types implement a method() which suits them. Here is a somewhat lengthy example which uses a virtual Output() method so that we see something on the Console.
It's noteworthy that each Key calls a method of an OutputterI, passing itself to it as a parameter; the outputter class then in turn calls back a method of the calling object. That's called "Double Dispatch" and combines run-time polymorphism with compile-time function overloading. At compile time the object and it's concrete type are not known; in fact, they can be implemented later (e.g. by inventing another Key). But each object knows what to do when its callback function (here: GetData()) is called.
using System;
using System.Collections.Generic;
namespace DoubleDispatch
{
interface KeyI
{ // They actually delegate that to an outputter
void Output();
}
interface OutputterI
{
void Output(KeyA kA);
void Output(KeyExtra kE);
void Output(KeyI k); // whatever this does.
}
class KeyBase: KeyI
{
protected OutputterI o;
public KeyBase(OutputterI oArg) { o = oArg; }
// This will call Output(KeyI))
public virtual void Output() { o.Output(this); }
}
class KeyA : KeyBase
{
public KeyA(OutputterI oArg) : base(oArg) { }
public string GetAData() { return "KeyA Data"; }
// This will compile to call Output(KeyA kA) because
// we pass this which is known here to be of type KeyA
public override void Output() { o.Output(this); }
}
class KeyExtra : KeyBase
{
public string GetEData() { return "KeyB Data"; }
public KeyExtra(OutputterI oArg) : base(oArg) { }
/** Some extra data which needs to be handled during output. */
public string GetExtraInfo() { return "KeyB Extra Data"; }
// This will, as is desired,
// compile to call o.Output(KeyExtra)
public override void Output() { o.Output(this); }
}
class KeyConsolePrinter : OutputterI
{
// Note: No way to print KeyBase.
public void Output(KeyA kA) { Console.WriteLine(kA.GetAData()); }
public void Output(KeyExtra kE)
{
Console.Write(kE.GetEData() + ", ");
Console.WriteLine(kE.GetExtraInfo());
}
// default method for other KeyI
public void Output(KeyI otherKey) { Console.WriteLine("Got an unknown key type"); }
}
// similar for class KeyScreenDisplayer{...} etc.
class DoubleDispatch
{
static void Main(string[] args)
{
KeyConsolePrinter kp = new KeyConsolePrinter();
KeyBase b = new KeyBase(kp);
KeyBase a = new KeyA(kp);
KeyBase e = new KeyExtra(kp);
// Uninteresting, direkt case: We know at compile time
// what each object is and could simply call kp.Output(a) etc.
Console.Write("base:\t\t");
b.Output();
Console.Write("KeyA:\t\t");
a.Output();
Console.Write("KeyExtra:\t");
e.Output();
List<KeyI> list = new List<KeyI>() { b, a, e };
Console.WriteLine("\nb,a,e through KeyI:");
// Interesting case: We would normally not know which
// type each element in the vector has. But each type's specific
// Output() method is called -- and we know it must have
// one because that's part of the interface signature.
// Inside each type's Output() method in turn, the correct
// OutputterI::Output() for the given real type was
// chosen at compile time dpending on the type of the respective
// "this"" argument.
foreach (var k in list) { k.Output(); }
}
}
}
Sample output:
base: Got an unknown key type
KeyA: KeyA Data
KeyExtra: KeyB Data, KeyB Extra Data
b,a,e through KeyI:
Got an unknown key type
KeyA Data
KeyB Data, KeyB Extra Data
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.
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*/
}
}
This is C# 4.0.
I have a class that stores WeakReferences on some Actions like that:
public class LoremIpsum
{
private Dictionary<Type, List<WeakReference>> references = new Dictionary<Type, List<WeakReference>>();
public void KeepReference<T>(Action<T> action)
{
if (this.references.ContainsKey(typeof(T)))
{
this.references[typeof(T)].Add(new WeakReference(action));
}
else
{
this.references.Add(typeof(T), new List<WeakReference> { new WeakReference(action) });
}
}
}
This class has another method allowing to execute the Actions passed to it later but it's of little importance in this question.
and I consume this class this way:
public class Foobar
{
public Bar Bar { get; set; }
public void Foo(LoremIpsum ipsum)
{
ipsum.KeepReference<Bar>((b) => { this.Bar = b; });
ipsum.KeepReference<Bar>(this.Whatever);
}
public void Whatever(Bar bar)
{
// Do anything, for example...:
this.Bar = bar
}
}
Bar being a third class in my application.
My question:
In the KeepReference method, how can I know if the Action passed in parameter refers to an anonymous method (this.Bar = b;) or a concrete method (this.Whatever)?
I checked the properties of action. I couldn't find any property on action (like IsAbstract) of a IsAnonymous kind. The underlying type is MethodInfo which makes sense because after compiling I can see in ildasm the anonymous method "became" a normal method on Foobar. In ildasm I can also see that the anonymous method is not a full pink square but a white square surrounded by pink and in its definition there's a call to some CompilerServices classes but I don't know how to take advantage of this back in C#. I'm sure it's possible to get to know about the real nature of action. What am I missing?
For the sake of having an "accepted" answer on this question, I went as per the link given by Michael Kjörling in his first comment on my question.
if (action.Target.GetType().GetMethods().Where(method => method.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any()).Contains(action.Method))
{
// ...
}
Compiler generated methods will always have their names with angled brackets like below
Void <Main>b__0()
so why not just fetch the name and see if it has angled brackets in it.
Action someaction = () => Console.Write("test");
string methodName= RuntimeReflectionExtensions.GetMethodInfo(someaction).ToString();
if(methodName.Contains("<"))
Console.write("anonymous");
or you can use much better pattern matching with regex