I have a method that accepts an Action with a signature like:
public void DoSomething(Action code);
then I would call this method like:
DoSomething(()=> CallSomething("A","B","C");
In the DoSomething method, how can I get the argument values?
Another thing to consider is that CallSomething can potentially have optional parameters, meaning I can't just change the signature of DoSomething to -> Expression<Action>
All I need to do is get the argument values, I'm interested in any method that can work.
I've already tried to create a new method which accepts Expression<Action> then pass the Action through (From DoSomething), but the arguments weren't populated.
Any suggestions welcome.
The point is you don't want to.
Your method accepts an Action delegate. It's saying "I only want something to call that has no arguments and returns no value".
If you need to pass arguments to the function, either use a different delegate, or pass them as arguments directly.
Think about this without the lambda. You have an interface that has a single method, Act that takes no arguments and returns no value.
DoSomething(IMyInterface myInterface)
{
myInterface.Act(); // How do I get the arguments of some method that `Act` calls?
}
Does this make any sense whatsoever? Would you expect to be able to disassemble the whole instance that's passed in myInterface, find its Act method, go through all of the methods that are called from there and intercept their arguments? Delegates are little but a single-method interface with a bit of state carried over.
If you need the arguments, make them part of the public interface. Otherwise, your abstraction has no meaning whatsoever, and you shouldn't be using it. Nobody is forcing you to use lambdas, and nobody is forcing you to pass a single lambda and no arguments, and nobody is forcing you to use Action in particular. They are all simple tools - if they don't fit your task, don't use them.
To answer your question more directly: you get the arguments as any other arguments. The problem is that your action has no arguments.
Related
For a test, I want to create a generic "helper" method which will take take two arguments, the first argument is a function (or a reference to the function) and the 2nd argument is a list of objects for that function that are to be called as its parameters.
The following does this perfectly:
CallMyFunctionWithParamsPlease(new Func<int, int>(MyMethod), new object[] {1});
public static int CallMyFunctionWithParamsPlease(Delegate func, params object[] args)
{
func.DynamicInvoke(args);
return 3;
}
The thing is, this doesn't look very nice when calling it and I wish to abstract it into another method to act as syntatic sugar.
Ideally I want it to be called like this:
CallMyFunctionWithParamsPlease(myMethod, new Object[] {1});
From what I can gather, there is no elegant solution to do this in C# since I cannot pass myMethod by itself as a reference anywhere, instead I must pass it by declaring a new Func along with the return type of the method. Since I'm not using this return type anywhere, I'm not sure why it's necessary to input this information. My limited understanding is that because C# is statically typed, the compiler must know everything and things like this just aren't possible.
Is this true or not? How would I create syntatic sugar to simply pass a method to another method which can be called there without needing to invoke "new Func"? I would have thought simply passing the function as a reference pointer would allow me to do this, but I'm having difficultly doing this too. I looked into delegates, using "unsafe" with pointers, and a few other options. None of them seem to make this possible, or if they do, they didn't explain it in a manner that I could understand.
I simply want to pass a method to another method, and invoke it with a variable list of object params with variable length whereby I don't need to specify this whilst invoking it. I'm not sure if I'm trying to force C# to do something it's not meant to do here, and instead I'd be better off using a dynamically typed language to do this. The problem is I really enjoy the intellisense that the static typing of C# offers, along with the performance improvements over a language like Python. I'd just like a way to syntactically abstract away the boilerplate with my own helper methods for things like this.
UPDATE: Thanks to the comments here it seems I can do this with a lambda expression nice and elegantly. The signature can be simply changed to public static long CallMyFunctionWithParamsPlease<T>(Func<T> func)
If deferred execution is what you want simply pass a Func<TReturnType> to your method (or class). The calling method doesn't need to know how many parameters are involved.
e.g. Assuming MyMethod has a signature int MyMethod(int arg):
CallMyFunctionWithParamsPlease(() => MyMethod(1));
public static int CallMyFunctionWithParamsPlease(Func<int> func)
{
return func();
}
If MyMethod takes two parameters, it's the same call:
CallMyFunctionWithParamsPlease(() => MyMethod(1, 2));
I need to understand how a developer can make use of Action delegates and lambdas. I will give an example:
For example, using MOQ, you write something like:
var repoMock = new Mock<IMyInterface>();
repoMock.Setup(r => r.GetData()).Returns(new string[] {"one", "two", "three"});
My point is, how's the code inside "Setup" and "Returns" is making use of the input (lambda expression)?
If you look at the type signatures for the Moq methods, you will notice that Setup and Returns are actually doing to very different things. Returns takes a delegate (a Func<TResult> or a Func<T, TResult>), but Setup actually takes an Expression, which is a much more complex data type. More details about the difference between Func<T> (a delegate) and Expression<Func<T>> (an expression) can be found in this related answer. The rest of my answer will try to explain how Moq, specifically, uses those two different types for two different reasons. Hopefully that will at least get you started in how to use them in your own code.
Delegates, whether they be named, anonymous, or lambda expressions, are .NET's way of permitting functions to be used as a "first class" objects; that's just a fancy way of saying that delegates can be used in all the same ways that the primitive types: you can declare local delegates, pass delegates as parameters, and return delegates from methods. You "call" a delegate the same way you call any other function: you use the () syntax.
In your case, you used the overload of Returns that doesn't actually take a delegate, it simply takes an value that will be returned whenever the associated mocked method is called. However, there are overloads of Returns that do take delegates, so you could have equivalently written this:
.Returns(() => new string[] {"one", "two", "three"}};
or
.Returns(x => x.produceStringArray("one", "two", "three"));
In either case, the Returns method will be given a delegate, of the appropriate type, as a parameter. Internally, all Returns really does is to save the delegate as part of the mocked object instance. Later, when the mocked method gets called, the delegate is executed to return the correct value. While the real Moq internals are more complex that this, the basic idea is something like the following:
private Func<T> returnMe;
public void Returns<T>(Func<T> myDelegate)
{
this.returnMe = myDelegate;
}
public T Execute()
{
return this.returnMe();
}
As you can see, once you have a delegate, you can just call it like any other function; when the compiler sees a lambda expression somewhere that it expects a delegate, it compiles the lambda expression into an anonymous delegate and that's what gets passed into your method.
The Setup method, on the other hand, is far more complex. The lambda expression there is not being passed as a Func<T>, but as an Expression<Func<T>>. What this means is, the compiler is not compiling the lambda expression into a delegate, but rather, into an expression tree. The objects in an expression tree are special types of object that represent the various things that a method can do. Compilers produce expression trees out of your source code all the time, but usually those expression trees are immediately used to produce machine code. When the C# compiler compiles an Expression, however, it actually leaves the expression tree in it's "half-compiled" state. You can finish compiling an expression, and run the resulting code if you want, but that's not the only way they are used. Your program can also examine the expression tree and see all the details about what the code "would do" if it were compiled and run, and use that information however it wants.
When you call a Moq method like this:
moq.Setup(x => x.MyMethod(1, 2, 3)).Returns(true);
the Setup method can use the expression tree to figure out the name of the method, and the types and values of the parameters, that you wrote on the right-hand side of your lambda. In this case, Moq never executes your lambda expression, merely examines it. It creates an internal object that is associated with the specific method call you just set up, and records the various things you associate with that method (e.g. the Return calls.) Later on, when you use your mocked object in a unit test, Moq will intercept every method call you make on your object, and scan its list of set-up methods looking for one that matches the call, and produce whatever mocked-up behavior you've specified about that call.
It is like the Setup method calls (or stores a reference to, for future use) a method with parameter "r" which returns r.GetData() value.
I'm using BitFactory logging, which exposes a bunch of methods like this:
public void LogWarning(object aCategory, object anObject)
I've got an extension method that makes this a bit nicer for our logging needs:
public static void LogWarning(this CompositeLogger logger,
string message = "", params object[] parameters)
Which just wraps up some common logging operations, and means I can log like:
Logging.LogWarning("Something bad happened to the {0}. Id was {1}",foo,bar);
But when I only have one string in my params object[], then my extension method won't be called, instead the original method will be chosen.
Apart from naming my method something else, is there a way I can stop this from happening?
The rules about how overloaded methods are resolved to one (or an error) are complex (the C# specification is included with Visual Studio for all the gory details).
But there is one simple rule: extension methods are only considered if there is no possible member that can be called.
Because the signature of two objects will accept any two parameters, any call with two parameters will match that member. Thus no extension methods will considered as possibilities.
You could pass a third parameter (eg. String.Empty) and not use it in the format.
Or, and I suspect this is better, to avoid possible interactions with additions to the library (variable length argument list methods are prone to this) rename to LogWarningFormat (akin to the naming of StringBuffer.AppendFormat).
PS. there is no point having a default for the message parameter: it will never used unless you pass no arguments: but that would log nothing.
Declared methods are always preceding extension methods.
If you want to call the extension regardless of the declared method, you have to call it as a regular static method, of the class that declared it.
eg:
LoggerExtensions.LogWarning(Logging, "Something bad happened to the {0}. Id was {1}",foo,bar);
I assume that the extension is declared in a class named LoggerExtensions
Provided that I think a method with a different name is the way to go (easier to read and maintain), as a workaround you could specify parameters as a named parameter:
logger.LogWarning("Something bad happened to the {0}.", parameters: "foo");
I want to write a wrapper for the System.Web.Caching.Cache, which handles my cache requests.
I need a method, which can invoke a callback method, if the cache entry doesn't exist. The problem is: I dont know how many params the callback method has:
public T Get<T, TCallback>(string key, TCallback func) where TCallback : Func<T>
{
// check cachekey, do sth
T result = func.Invoke();
return result;
}
With this implementation it's possible to give a callback without params. But what if I have some?
Thanks,
trial
This method should only accept the parameters that this implementation wants to send to a given function. If it has no information that would be relevant to such a callback then it should simply require a parameter-less delegate. If it has parameters that will be needed for some, but won't be needed for others, it should provide them in all cases, using a single delegate.
It then becomes the responsibility of the caller to match the function that they want to call with the signature of the delegate. If they want to fix values for some function that has parameters your callback doesn't have, or if they want to call a function with less parameters, etc. it is their responsibility to make the "conversion", rather than this method's responsibility to deal with a delegate with an unknown signature.
The use of lambdas makes "converting" functions very easy; much easier than the alternative. To fix a value for a parameter when your callback doesn't have one, you can close over the variable:
int value = 5;
Get("key", () => SomeMethod(value));
You can also use a lambda to ignore a parameter:
Get("key", someParameterToIgnore => AnotherMethod());
1) You can use dynamic or Dictionary as parameter of your callback. Put in Dictionary or dynamic string value - like CallbackType.
Its bad because you lost static type analysing, but it possible.
2)It may be useful: Ellipsis notation in C#?
I would like to know about the Invoke(delegate) method. I do not understand why I do not need to specify arguments. What if I need them supply..Hopefully below you better understand what I mean. Thank you
EventHandler a = new EventHandler(this.A);
Invoke(a); //where doest it take the arguments from?
a(); //does not work, missing arguments
Because Invoke is meant to be used on Windows Forms, and the pattern for events used here is well specified, the Invoke method can make an educated guess. In fact, it is documented on MSDN exactly what it does, if you try to invoke an EventHandler without parameters using Invoke:
The delegate can be an instance of EventHandler, in which case the
sender parameter will contain this control, and the event parameter
will contain EventArgs.Empty.
You can, and should, use the overload of Invoke that allows you to specifiy the parameteres of your delegate, in order to make it more explicit what is going on. Also, calling Invoke without the parameters array will only work for delegates of type EventHandler (or, of course, delegates that does not take any parameters in the first place).
I don't work with EventHandlers but I do use dynamic invocation on delegates. Normally, for me at least, the code ends up looking like this
a.Invoke(new object[] { arg0, .... argn });