Explanation for lambda expression C# - 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.

Related

How do I save result in string of executed command

As the title says how can I save in string the result of the executed command?
SendCommand("server.hostname");
My code:
public void SendCommand(string command)
{
PacketModel packet = new PacketModel()
{
Identifier = 1,
Message = command,
Name = "RustManager"
};
string packetString = JsonConvert.SerializeObject(packet);
_webSocket.SendAsync(packetString, null);
}
public void GetServerHostname()
{
SendCommand("server.hostname");
}
Due to my small reputation I cannot comment - which is what I would have done before that.
Normally methods that end on Async are async and return a Task<T> type.
Using the await keyword makes your method async which is why you have to mark it as async in the method head.
Link to C#-Documentation on the await keyword
It is really hard to say how to get your code running since I don't have alot of information but maybe this helps:
public async void SendCommand(string command)
{
PacketModel packet = new PacketModel()
{
Identifier = 1,
Message = command,
Name = "RustManager"
};
string packetString = JsonConvert.SerializeObject(packet);
var result = await _webSocket.SendAsync(packetString, null);
}
EDIT 1:
After getting some new information here is my new answer:
You use this class for your websocket. If you look at the signiture of the "SendAsync" method you can see, that it returns void (which means "nothing"). So you will not be able to "Store some kind of information" here.
The method looks like this:
public void SendAsync (string data, Action<bool> completed)
{ [...] }
You will have to listen to the WebSocket and wait for a server-side response. It seems, that the library supports that via events:
ws.OnMessage += (sender, e) => {
...
};
So you can define an eventhandler to process the server-response.
If you would like to get the message data, you should access e.Data or e.RawData property.
e.Data property returns a string, so it is mainly used to get the text message data.
(source (GitHub Readme))
So to fullfil your wishes try the following:
1.) At initialization of your _websocket instance subscribe to the .OnMessageevent with a corresponding event handler. (Some information about that)
2.) Send your message as you do it now with SendAsync
3.) If your server responds with a message to the network socket, the OnMessageevent will fire and you will be able to get the Data from the Eventargument e
(I did not test this - but it should work since it is used this way in the examples)

Action <T> usage as parameter

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).

Effective way to invoke generic interface method in runtime

I'm working on the some kind of EventSourcing architecture and have 2 main concepts in my app - events and handlers.
Events example:
class NewRecordCreated: EventMessage {...}
And there some handlers looks like:
class WriteDBHandler: IEventHandler<NewRecordCreated>, IEventHandler<RecordUpdated> {
public void Handle(NewRecordCreated eventMessage) {...}
public void Handle(RecordUpdated eventMessage) {...}
}
And also I have custom implementation of queue protocol which dispatch events to proper handlers. So basically on app startup I parse assembly and create mapping between event and handlers based on types.
So when I actually dispatching events to handlers I based on event type getting chain of handler's types - something like var handlerChain = [typeof(WriteDbHandler), typeof(LogHandler), typeof(ReadModelUpdateHandler)] and for each of those handlers I need to invoke it's instance, then cast it to proper interface (IEventHandler<>) and than invoke Handle method.
But I can't cast to generic interface, since it's not possible. I think about options of implementing non generic version of interface, but it's seems quite unpleasant for me to add extra method implementation each time, especially if there no any real reasons for it.
I think about dynamic invocation or reflection, but both of this variants seems have performance issues. Maybe you could advice me some suitable alternatives?
Using reflection
Rather than trying to cast to IEventHandler<>, you can instead use reflection to get a reference to the method you need to invoke. The code below is a good example. It simplifies the "queue protocol" for sake of brevity, but it should sufficiently illustrate the reflection that you need to do.
class MainClass
{
public static void Main(string [] args)
{
var a = Assembly.GetExecutingAssembly();
Dictionary<Type, List<Type>> handlerTypesByMessageType = new Dictionary<Type, List<Type>>();
// find all types in the assembly that implement IEventHandler<T>
// for some value(s) of T
foreach (var t in a.GetTypes())
{
foreach (var iface in t.GetInterfaces())
{
if (iface.GetGenericTypeDefinition() == typeof(IEventHandler<>))
{
var messageType = iface.GetGenericArguments()[0];
if (!handlerTypesByMessageType.ContainsKey(messageType))
handlerTypesByMessageType[messageType] = new List<Type>();
handlerTypesByMessageType[messageType].Add(t);
}
}
}
// get list of events
var messages = new List<EventMessage> {
new NewRecordCreated("one"),
new RecordUpdated("two"),
new RecordUpdated("three"),
new NewRecordCreated("four"),
new RecordUpdated("five"),
};
// process all events
foreach (var msg in messages)
{
var messageType = msg.GetType();
if (!handlerTypesByMessageType.ContainsKey(messageType))
{
throw new NotImplementedException("No handlers for that type");
}
if (handlerTypesByMessageType[messageType].Count < 1)
{
throw new NotImplementedException("No handlers for that type");
}
// look up the handlers for the message type
foreach (var handlerType in handlerTypesByMessageType[messageType])
{
var handler = Activator.CreateInstance(handlerType);
// look up desired method by name and parameter type
var handlerMethod = handlerType.GetMethod("Handle", new Type[] { messageType });
handlerMethod.Invoke(handler, new object[]{msg});
}
}
}
}
I compiled this and ran it on my machine and got what I believe are the correct results.
Using run-time code generation
If reflection is not fast enough for your purposes, you can compile code on-the-fly for each input message type and execute that.
The System.Reflection.Emit namespace has facilities for doing just that.
You can define a dynamic method (not to be confused with the dynamic keyword, which is something else), and emit a sequence if IL opcodes that will run each handler in the list in sequence.
public static Dictionary<Type, Action<EventMessage>> GenerateHandlerDelegatesFromTypeLists(Dictionary<Type, List<Type>> handlerTypesByMessageType)
{
var handlersByMessageType = new Dictionary<Type, Action<EventMessage>>();
foreach (var messageType in handlerTypesByMessageType.Keys)
{
var handlerTypeList = handlerTypesByMessageType[messageType];
if (handlerTypeList.Count < 1)
throw new NotImplementedException("No handlers for that type");
var method =
new DynamicMethod(
"handler_" + messageType.Name,
null,
new [] { typeof(EventMessage) });
var gen = method.GetILGenerator();
foreach (var handlerType in handlerTypeList)
{
var handlerCtor = handlerType.GetConstructor(new Type[0]);
var handlerMethod =
handlerType.GetMethod("Handle", new Type[] { messageType });
// create an object of the handler type
gen.Emit(OpCodes.Newobj, handlerCtor);
// load the EventMessage passed as an argument
gen.Emit(OpCodes.Ldarg_0);
// call the handler object's Handle method
gen.Emit(OpCodes.Callvirt, handlerMethod);
}
gen.Emit(OpCodes.Ret);
var del = (Action<EventMessage>)method.CreateDelegate(
typeof(Action<EventMessage>));
handlersByMessageType[messageType] = del;
}
}
Then, instead of invoking the handlers with handlerMethod.Invoke(handler, new object[]{msg}), you just call the delegate like any other, with handlersByMessageType[messageType](msg).
Full code listing here.
The actual code generation is done in the GenerateHandlerDelegatesFromTypeLists method.
It instantiates a new DynamicMethod, gets its associated ILGenerator, and then emits opcodes for each handler in turn.
For each handler type, it will instantiate a new object of that handler type, load the event message onto the stack, and then execute the Handle method for that message type on the handler object.
This is of course assuming that the handler types all have zero-parameter constructors.
If you need to pass arguments to the constructors, though, you'll have to modify it considerably.
There are other ways to speed this up even more.
If you relax the requirement to create a new handler object with every message, then you could just create the objects while generating the code, and load them.
In that case, replace gen.Emit(OpCodes.Newobj, handlerCtor) with gen.Emit(OpCodes.Ldobj, handlerObjectsByType[handlerType]).
That gives you two benefits:
1. you're avoiding an allocation on every message
2. you can instantiate the objects any way you want when you populate the handlerObjectsByType dictionary. You can even use constructors with parameters or factory methods.

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.)

Using reflection to specify the type of a delegate (to attach to an event)?

What I effectively want to do is something like this (I realise this is not valid code):
// Attach the event.
try
{
EventInfo e = mappings[name];
(e.EventHandlerType) handler = (sender, raw) =>
{
AutoWrapEventArgs args = raw as AutoWrapEventArgs;
func.Call(this, args.GetParameters());
};
e.AddEventHandler(this, handler);
}
...
Now I know that the e.EventHandlerType will always derive from EventHandler<AutoWrapEventArgs>. However, I can't just do:
EventHandler<AutoWrapEventArgs> handler = (sender, raw) =>
{
AutoWrapEventArgs args = raw as AutoWrapEventArgs;
func.Call(this, args.GetParameters());
};
e.AddEventHandler(this, handler);
As .NET complains that there is no conversion applicable from EventHandler<AutoWrapEventArgs> to EventHandler<DataEventArgs> when AddEventHandler is called. This is the exact message:
Object of type 'System.EventHandler`1[IronJS.AutoWrapObject+AutoWrapEventArgs]'
cannot be converted to type
'System.EventHandler`1[Node.net.Modules.Streams.NodeStream+DataEventArgs]'.
I have also tried using Invoke to dynamically use the constructor of e.EventHandlerType, but there's no way to pass the delegate definition to Invoke()'s parameter list (because there is no conversion from delegate to object).
Is there a way I can use reflection to get around this problem?
Bingo! The trick is to get a reference to the constructor for the delegate type and then invoke it using the following parameters:
The target object of the delegate (backend.Target)
The delegate's pointer (backend.Method.MethodHandle.GetFunctionPointer())
The actual code that does this looks like (t in this case is the generic argument provided to EventHandler<> during inheritance):
Type t = e.EventHandler.GetGenericArguments()[0];
Delegate handler = (Delegate)
typeof(EventHandler<>)
.MakeGenericType(t)
.GetConstructors()[0]
.Invoke(new object[]
{
backend.Target,
backend.Method.MethodHandle.GetFunctionPointer()
});
You can then use the delegate for the event adding like so:
e.AddEventHandler(this, handler);
You can use Delegate.CreateDelegate to accomplish your goal like this:
public void RegisterHandler(string name)
{
EventInfo e = mappings[name];
EventHandler<AutoWrapEventArgs> handler = (s, raw) =>
{
func.Call(this, raw.GetParameters());
};
e.AddEventHandler(this, Delegate.CreateDelegate(e.EventHandlerType, null, handler.Method));
}

Categories

Resources