How to create an Action from another with an additional parameter? - c#

Is there a class available in the .Net Framework which wraps an Action and another parameter just like EnhancedAction in the following example?
private void Test(string s)
{
// I would like :
// Method1(EnhancedAction.Create(Method2, s));
// But I must write :
Method1(i => Method2(i, s));
}
private void Method1(Action<int> myAction)
{
myAction(1);
}
private void Method2(int i, string s)
{
}

You've already shown how to write the code; you merely need to create your own class that has that exact solution to implement the method you're asking for:
class EnhancedAction
{
public static Action<T1> Create<T1, T2>(Action<T1, T2> action, T2 parameter2)
{
return parameter1 => action(parameter1 , parameter2);
}
}
Although I fail to see how this is easier to write out than just using the lambda directly.

I found Umbrella which provides what I was looking for : http://umbrella.codeplex.com/SourceControl/latest#Main/Src/Umbrella/Binding/CurryExtensions.cs
Though it doesn't seem very active lately.

Related

Call Method based on Type of Parameter

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.

Why it is not possible to assign a delegate to a method group?

Having the following class:
class C {
public void OneMethod(string s) {
}
public void ChangeMethods() {
OneMethod = delegate(string s) { };
}
}
The compiler says:
Error 1 Cannot assign to 'OneMethod' because it is a 'method group'
Why is that? Should I create a method group instead?
You simply can't change how a class behaves like this.
Method groups are only used in method invocation expressions and when creating delegate instances.
If you want a class which can behave dynamically like this, you should perhaps look at ExpandoObject. Or if you want to be able to make your OneMethod class do something based on a delegate which varies, you can easily hook that up simply enough using a field of the relevant delegate type:
class C {
private Action<string> action = delegate {};
public void OneMethod(string s) {
action(s);
}
public void ChangeMethods() {
action = delegate(string s) { };
}
}
It's somewhat unusual to want to do this, admittedly.

How to pass in a lambda and have access to a particular set of methods

I want to have something like:
AStaticClass.MakeCall(commonCmds => commonCmds.MethodOfAParticularClass)
So I want to have a lambda expression as an argument and have the delegate list the available set of methods of a particular class that I can access through intellisense with the lambda function. Then make a call to the passed in method.
i.e. commonCmds => commonCmds. {Lists all the methods of a particular class}
and then I want to have a method that makes that call.
I can't figure it out the proper method signature.
So far I have public void MakeCall(Action cmd) {cmd.invoke;} THis obviously does not work. I tried func, Expression and cannot figure it out.
Thank you so much for the help!
EDIT:
CmdsTwo and CmdsOne Can be static. However I would like to my classes up in this way, since it will make a lot my other work much easier.
public void Main(string []args) {
MyStaticClass.MakeCall(x => x.DoThis);
MyStaticClass.MakeCallTwo(x => x.DoThisTwo);
MyStaticClass.MakeCall(x => x.DoThisThree);
}
public static class MyStaticClass{
public static void MakeCall<???>( ??????)
public static void MakeCallTwo<???>( ??????)
}
public class Cmds{
public void DoThis();
public void DoThisThree();
}
public class CmdsTwo{
public void DoThisTwo();
}
}
The closest i can think of right now is this:
commonCmds => commonCmds.GetType().GetMethods()
This returns you an array of MethodInfo, which describe all methods of the type of commonCmds. You'd have to invoke one of those like this:
object result = someMethodInfo.Invoke(someObjectInstance, new object[] { someParameter });
You can check it
AStaticClass.MakeCall( () => commonCmds.MethodOfAParticularClass)
You need to use the generic version of Action With A Type.
public void MakeCall(Action<TYPE_HERE> cmd)
{
cmd.Invoke(...);
}
The type gets inferred and intellisense should kick in.
So I got it. Iused an extension method. Thank you.
public static class MyStaticClass{
public static void MakeCall(Action<Cmds> paramater){
Helper(new Cmds(), parameter);
}
private static void Helper(this Cmds, Action<Cmds> invokeThis) {...}
public static void MakeCallTwo<???>( ??????)
}

C#: Creating an instance of an abstract class without defining new class

I know it can be done in Java, as I have used this technique quite extensively in the past. An example in Java would be shown below. (Additional question. What is this technique called? It's hard to find an example of this without a name.)
public abstract class Example {
public abstract void doStuff();
}
public class StartHere{
public static void main(string[] args){
Example x = new Example(){
public void doStuff(){
System.out.println("Did stuff");
}
};
x.doStuff();
}
}
Now, my main question would be, can this also be done in C#, and if so, how?
The Java technique is called "Anonymous inner class", and there is no equivalent in C#.
With lamba expressions and class initializers you can get the same behaviour with a bit of effort.
public class Example {
public Action DoStuff;
public Action<int> DoStuffWithParameter;
public Func<int> DoStuffWithReturnValue;
}
class Program {
static void Main(string[] args) {
var x = new Example() {
DoStuff = () => {
Console.WriteLine("Did Stuff");
},
DoStuffWithParameter = (p) => {
Console.WriteLine("Did Stuff with parameter " + p);
},
DoStuffWithReturnValue = () => { return 99; }
};
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
One problem with this solution that I just realized is that if you were to create fields in the Example class, the lambda expressions would not be able to access those fields.
However, there is no reason that you could not pass the instance of Example to the lambda expressions which would give them access to any public state that example might hold. AFAIK that would be functionally equivalent to the Java Anonymous Inner Class.
P.S. If you are going to vote an answer down, do us all a favour and add a comment as to why you disagree :-)
Typically, problems that are solved with anonymous inner classes in Java are solved in a much cleaner fashion using delegates in .Net. Your example is a little too simplistic to determine your intent. If your intent by using the abstract class is to pass around a "behavior" think about just using an Action delegate instead.
public class StartHere{
public static void main(string[] args){
Action doStuff = () => Console.WriteLine("Did stuff");
executeSomething(doStuff);
}
public static void executeSomething(Action action)
{
action();
}
}
That can't be done in C#; you need to declare a new class type. The closest you can get in C# is probably a named nested class:
public class StartHere{
private class Foo : Example {
public override void doStuff()
{
Console.WriteLine("did stuff");
}
}
public static void Main(string[] args){
Example x = new Foo();
x.doStuff();
}
}
This is not supported in C#, and if it were up to me it shouldn't be so either.
The proliferation of inner classes in java is mainly due to the lack of delegates or lambdas, which C# has. So while this type of functionality currently is "your only hope" in java, you can usually use other mechanisms in C# to achieve the same ends. Java feels like playing the piano with one hand in this regard.
(Admittedly a lot of us have gotten quite good at this one-handed playing; and now it seems like we have to wait at least until java 8 for closures...)
Since your class represents only an action, you can use a delegate in your case, there is an existing delegate :
public delegate void Action();
This is the exact equivalent of your class.
And the déclaration of your anonymous class is even cleaner :
Action action = () => Console.WriteLine("Hello world");
action(); // invoke
you can even use closure :
public void Hello(string name)
{
Action action = () => Console.WriteLine("Hello " + name);
action(); // will call the above lambda !
}
While all good answers, most of the work arounds suggested rely on C# 3.0
So, for the sake of completeness, I'll add another solution that uses neither lambdas nor Func type (Granted that, as Matt Olenik mentioned in the comments, one could generalize the below delegates to work the same way.). For those, like me who may still be working with C# 2.0. Maybe not the best solution, but it works.
public class Example
{
public delegate void DoStuffDelecate();
public DoStuffDelecate DoStuff;
public delegate void DoStuffWithDelecate(int n);
public DoStuffWithDelecate DoStuffWithParameter;
public delegate int DoStuffWithReturnDelecate();
public DoStuffWithReturnDelecate DoStuffWithReturnValue;
}
class Program
{
static int MethodWithReturnValue()
{
return 99;
}
static void MethodForDelecate()
{
Console.WriteLine("Did Stuff");
}
static void MethodForDelecate(int n)
{
Console.WriteLine("Did Stuff with parameter " + n);
}
static void Main(string[] args)
{
var x = new Example();
x.DoStuff = MethodForDelecate;
x.DoStuffWithParameter = MethodForDelecate;
x.DoStuffWithReturnValue = MethodWithReturnValue;
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
You are able to accomplish this with Mocking in .NET. However there is no in-language support for this feature, I think it will be available in C# 4.0. There are a number of libraries out there for Mocking, including:
Moq
RhinoMock
In short no, you have to define it as separate sub class. I think this feature is coming C# 4.0 though?
Edit: No it's not coming C# 4.0 I made that up.

C# delegate for two methods with different parameters

I am using the following methods:
public void M1(Int32 a)
{
// acquire MyMutex
DoSomething(a);
// release MyMutex
}
and
public void M2(String s, String t)
{
// acquire MyMutex
DoSomethingElse(s, t);
// release MyMutex
}
From what I have found so far it seems that it is not possible to use a single delegate for two methods with different signatures.
Are there any other alternatives to write something like this:
public void UsingMutex(...)
{
// acquire MyMutex
...
// release MyMutex
}
UsingMutex(M1);
UsingMutex(M2);
All I can think for the moment is to use two delegates and a boolean flag to know which delegate to call, but it is not a long term solution.
It is possible to combine generics with delegates? And if so, do you have some links for any kind of documentation?
Environment: C# 2.0
Absolutely you can mix delegates with generics. In 2.0, Predicate<T> etc are good examples of this, but you must have the same number of args. In this scenario, perhaps an option is to use captures to include the args in the delegate?
i.e.
public delegate void Action();
static void Main()
{
DoStuff(delegate {Foo(5);});
DoStuff(delegate {Bar("abc","def");});
}
static void DoStuff(Action action)
{
action();
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Note that Action is defined for you in .NET 3.5, but you can re-declare it for 2.0 purposes ;-p
Note that the anonymous method (delegate {...}) can also be parameterised:
static void Main()
{
DoStuff(delegate (string s) {Foo(5);});
DoStuff(delegate (string s) {Bar(s,"def");});
}
static void DoStuff(Action<string> action)
{
action("abc");
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Finally, C# 3.0 makes this all a lot easier and prettier with "lambdas", but that is another topic ;-p
Yes, it's possible to combine generics with delegates.
public delegate void Action<T>(T x);
public delegate void Action<T,U>(T x, U y);
public void UsingMutex<T>(Action<T> x, T t) {
// acquire mutex...
x(t);
// release mutex...
}
public void UsingMutex<T,U>(Action<T,U> x, T t, U u) {
// acquire mutex...
x(t, u);
// release mutex...
}
But you still have to handle different number of parameters using overloads.
If you look at the Func<T> and Action<T> delegates in the framework, you'll see that they define a number of similar delegates with different number of parameters. You can use generics, but that doesn't solve the number of arguments issue you're talking about.

Categories

Resources