Action <T> usage as parameter - c#

I just started with .net core and found Action<T> used everywhere. I have provide sample code from Swagger code block below. My question is what is the use of using Action<T> here? I need to pass config data. How does Swagger extract that configuration data?
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "My API",
Description = "My First ASP.NET Core Web API",
TermsOfService = "None",
Contact = new Contact() { Name = "Talking Dotnet", Email = "x#x.com", Url = "www.x.com" }
});
});5

It's a lambda function which does not return anything. You could supply a void returning method there.
Here it's just used so that you can supply a function that does something with T. It means the library can create a default options object and give you a way of modifying it.
The method would be doing something like
public void AddFoo(Action<FooOptions> configure) {
// Create a default configuration object
var options = new FooOptions();
// Let the action modify it
configure(options);
// Do something with the now configured options
}

When you see a variable or a parameter of type Action, that means it is a reference to a method call. For example:
//Declare a method with no parameters
void ShowMessage()
{
Console.WriteLine("Hello world");
}
//Store a reference to that method in x
Action x = ShowMessage;
//Call that method
x(); //Displays "hello world"
Using a lambda expression, you can also define the method body inline, like this:
//Declare a lambda expression and store a reference to it in x
Action x = () => Console.WriteLine("Hello world");
//Call that method
x(); //Displays "hello world"
Now what if you need to store a reference to a method that takes parameters? Well, Action<T> is generic, meaning that various kinds of Action<T> can take parameters of different types. For example, an Action<string> can accept a string parameter.
void ShowMessage(string message)
{
Console.WriteLine(message);
}
Action<string> x = ShowMessage;
x("Hello world"); //Displays "Hello world"
Or as a Lambda:
Action<string> x = message => Console.WriteLine(message);
x("Hello world"); //Displays "Hello world"
When a method accepts an action as an argument, is is typically going to be used as a callback. For example, LINQ's Where method accepts a delegate that is executed for each item in a list and uses its output to determine whether the item should be included in the results.
With AddSwaggerGen you are providing a reference to a method that Swashbuckle will call at some point. I believe the method in this case is supposed to generate Swagger (typically using SwaggerDoc).

Related

Explanation for lambda expression C#

public static void GetUserAccessToken(string email, string password,string deviceToken,
Action onCompletion, Action<RestError> onError)
{
WebRequestBuilder builder = new WebRequestBuilder()
.Url(GetApiUrl(Urls.USER_ACCESS_TOKEN))
.Verb(Verbs.POST)
.ContentType(ContentTypes.FORM)
.FormData(Attributes.CLIENT_ID, Config.Api.PasswordGrantClientId)
.FormData(Attributes.CLIENT_SECRET, Config.Api.PasswordGrantClientSecret)
.FormData(Attributes.EMAIL_ID, email)
.FormData(Attributes.PASSWORD, password)
.FormData(Attributes.DEVICE_TOKEN, deviceToken)
.FormData(Attributes.SCOPE, "*");
AddClientAuthHeader(ref builder);
_instance._restUtil.Send(builder, handler =>
{
var response = DataConverter.DeserializeObject<ApiResponseFormat<UserToken>>(handler.text);
UserAccessToken = response.Data.AccessToken;
UserRefreshToken = response.Data.RefreshToken;
onCompletion?.Invoke();
}, restError =>
I cant understnad this line:
_instance._restUtil.Send(builder, handler => { var response = DataConverter.DeserializeObject<ApiResponseFormat<UserToken>>(handler.text);
and specifically from where and how its going to get the value for handler.text since i cannot see where it is defined or passed as a parameter
Think about lambda expressions as little methods, the lambda that you referenced would be something like this:
void Foo (Handler handler) // i am assuming that handler is of type Handler here
{
// do whatever you want
}
there the 'handler' variable is passed to the lambda as parameter just like in the method above, the text field inside handler, is just a normal instance field provided by the supposed Handler type.
Than the implementation of the Send method is responsible to pass a Handler as argument to the lambda invocation.

Anonymous methods not omitting parameters anymore?

I have been workig on a report on delegates for some time now in addition to working with them for over a year.
Looking up some info on the differences between anonymous methods used in C# 2.0 and lambda expressions in C# i read something about a functionality that 2.0 anonymous methods provide which lambda's dont: they can omit the parameter list.
After doing some research on this i try testing this out on my personal IDE which is running the latest version of C#, finding out that when i try to assign an anonymous method without any parameters to my Delegate type using them i get an error:
Delegate Test.MyHelloDelegate does not take 0 arguments
class TestClass
{
public delegate void MyHelloDelegate (string s);
MyHelloDelegate Hello = delegate () { Console.WriteLine("Hello from delegate"); };
private void CallHello ()
{
Hello("dummy");
}
}
My own assumption would be that it got patched out since people will only use lambda's anyway but i do need some evidence for that since i will be putting it in my report. Would love to know if someone has any idea what is going on with this.
Yes, cause your attached anonymous method doesn't takes an input parameter. Change it to
public delegate void MyHelloDelegate (string s);
MyHelloDelegate Hello = delegate(string s) { Console.WriteLine("Hello from delegate " + s); };
If you don't want pass any parameter then consider using the syntax below
MyHelloDelegate Hello = delegate { Console.WriteLine("Hello from delegate "); };

C# Invoke Method Console Write Demo

The code snippet below is from an ASP.NET MVC application. It accepts all parameters from browser. I believe it's vulnerable.
I'm testing an application's security, it uses Invoke method, but accepts the Object type, method and parameters dynamically from user's input. I believe it is dangerous and I'm trying to prove it.
Do you think I can invoke Console.Write or execute some sort of arbitrary/dangerous code?
I want to try to use C# Invoke Method to write to console to prove the vulnerability. This is what I did:
static void Main(string[] args)
{
Type magicType = Type.GetType("System");
ConstructorInfo magicConstructor = magicType.GetConstructor(Type.EmptyTypes);
object magicClassObject = magicConstructor.Invoke(new object[] { });
MethodInfo magicMethod = magicType.GetMethod("Console.Write");
object magicValue = magicMethod.Invoke(magicClassObject, new object[] { 100 });
}
But it doesn't work. It says Object is not initialized. What am I missing?
System is not a type, it's a namespace. You're actually looking for System.Console, which is the console class. After that, you're looking for the WriteLine method with the proper overload, which takes an int, which is what you pass to Type.GetMethod. Only then, you can invoke the MethodInfo object using Invoke passing null as the object (as this is a static class) and the right parameter.
What you actually want is this:
Type magicType = Type.GetType("System.Console");
var method = magicType.GetMethod("WriteLine", new[] { typeof(int) });
method.Invoke(null, new object[] { 100 });

Passing a method as a parameter with zero or more parameters for the passed in method?

I'm trying to code what I've called a 'trigger'. They take an object, a function and some kind of activation criteria. Once activated, it runs the method on that object.
Here's a basic stripped down example. It works as expected for now. An example usage would be:
SomeObject myObj = new SomeObject();
MyTrigger trigger = new MyTrigger(myObj, "Delete");
trigger.Activate(); // calls myObj.Delete();
Now where I've called Invoke with null is where parameters can normally go (I think). The problem I'm having is getting the 'zero or more paramters' as a single parameter in the function declaration. I need a thrid parameter when creating MyTrigger that would be the parameters to pass during the Invoke.
Or is there an even better way to do it? I.e. Can I somehow pass the object, the function call and the parameters as a single parameter? Maybe two parameters?
You have to use delegates.
// rewrite your trigger constructor like this
class MyTrigger<TTarget>
{
public MyTrigger(TTarget target, Action<TTarget> action);
public void Activate()
{
this._action(this._target);
}
}
// now call it with or without parameters
SomeObject myObj = new SomeObject();
var trigger = new MyTrigger<SomeObject>(myObj, o => o.Delete(1234));
trigger.Activate();
You can also create a static helper class to make the creation code slightly simpler to write:
static class MyTrigger
{
public MyTrigger<TTarget> Create<TTarget>(TTarget target, Action<TTarget> action)
{
return new MyTrigger<TTarget>(target, action);
}
}
// now write the initialization code like this (you don't have to specify the type parameter anymore):
var trigger = MyTrigger.Create(myObj, o => o.Delete());
You could use the params keyword:
public Trigger(object targetObject, string methodName, params object[] parameters)
{
//"parameters" here will be an array of length 0 if no parameters were passed
}
MyTrigger trigger = new MyTrigger(myObj, "Delete"); //no parameters
MyTrigger trigger = new MyTrigger(myObj, "Delete", param1); //one parameter
MyTrigger trigger = new MyTrigger(myObj, "Delete", param1, param2); //two parameters
But I prefer Knagis' answer because it will also provide you compile-time safety (and likely the Trigger class will be far simplified and ditch any reflection that you probably have in there.)

Dynamically invoking a Void Method with a String name in C#

my application is currently reading in a list of methods that I need to invoke, from the Database, and putting them into strings.
I want to be able to invoke these methods by their name, and pass parameters to them.
Heres a simple example of what I want to achieve:
protected void Page_Load(object sender, EventArgs e)
{
...
...
string MethodOne = "CombineText";
string WordOne = "Hello";
string WordTwo = "World";
CombineText(WordOne, WordTwo);
}
public void CombineText(string WordOne, string WordTwo)
{
Console.WriteLine(WordOne+" "+WordTwo);
}
I've seen plenty of examples online about invoking static methods, but I can't figure out how to invoke Public Void methods by name from strings.
Does anybody have any ideas? Much Appreciated!
You can use reflection.
MethodInfo mi = this.GetType().GetMethod(MethodOne);
mi.Invoke(this, new object[] { WordOne, WordTwo };
I would recommend using a switch instead of trying to call the method based on it's name.
switch(MethodOne)
{
case "CombineText":
CombineText(WordOne, WordTwo);
break;
default:
Console.WriteLine("Invalid function: " + MethodOne);
break;
}
This has the advantage of ensuring that you only accept valid arguments, and provides a way to sanitize the inputs on a per-function basis before evaluating (maybe you want to strip spaces from WordTwo for one function, for instance, or you want to pass the longer one in as the first parameter regardless of order.).
Assuming the method is an instance method of the current type:
MethodInfo method = this.GetType().GetMethod(MethodOne);
method.Invoke(this, new[] { WordOne, WordTwo });
You need to look at reflection. You need to do something like this:
Type type = GetType();
MethodInfo method = type.GetMethod(Method);
Method.Invoke(this, new object[] { WordOne, WordTwo });
http://msdn.microsoft.com/en-us/library/8zz808e6.aspx
http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx

Categories

Resources