How to get method results with AsyncCallback? - c#

I hope you can help me with the following:
I have a WebService method which is supposed to return an array of CompensationPlanReturnReturn objects.
The method is called like this:
//This is the object I need to instanciate because it contains the method I wanna call
CompensationPlan_Out_SyncService test = new CompensationPlan_Out_SyncService();
//This is the method that is supposed to return me an array of CompensationPlanReturnReturn objects
//The data.ToArray() is the parameter the method need, then I pass the method that I wanna run when the method finishes and I dont know what to pass as the final parameter
test.BeginCompensationPlan_Out_Sync(data.ToArray(), new AsyncCallback(complete), null)
//The method description is:
public System.IAsyncResult BeginCompensationPlan_Out_Sync(CompensationPlanDataCompensationPlan[] CompensationPlanRequest, System.AsyncCallback callback, object asyncState)
//On this method I'd like to access to the resuls (the array of CompensationPlanReturnReturn) but I dont know how
private void complete(IAsyncResult result)
{
lblStatus.Text = "Complete";
}

You need to call test.EndCompensationPlan_Out_Sync(result), which will return the result of the asynchronous operation, or throw an exception if an error occurred.

Async methods breakdown into two submethods - Begin and End.
You need to call EndCompensationPlan_Out_Sync to get the actual result returned by method -
private void complete(IAsyncResult result)
{
var actualResult = test.EndCompensationPlan_Out_Sync(result);
lblStatus.Text = "Complete";
}

Try to use the AsyncState-Property and cast it the the given Type.
Like this:
cSACommand = (SACommand)Result.AsyncState;

Related

Extracting Action method args in c#

I have the following lambda:
public object Execute(Action<IMessage<object>> method)
{
}
obj.Execute(x => someObject.RunSomething(new SomeMessage{a = "b"}));
SomeMessage is implementing IMessage<T>
I would like inside Execute to get the params sent to RunSomething...
I'm looking for something like method.Target as IMessage<object> or method.Target as SomeMessage
How can that be achieved?
Thanks
Not sure what you want to achieve but isn't it more logic to have something like that ?
public object Execute(Action<IMessage<object>> method, IMessage<object> parameter)
{
method(parameter);
}
obj.Execute(someObject.RunSomething, new SomeMessage{a= "b"});
In that case you receive the parameter you will pass to the function. So you can do whatever you want with it.

can i pass the value for IAwaitable<bool>

I have a bot application where i have the below method, which i want to call explicitly in specific case rather than waiting for user input. i have the context object but how can i pass the true here
//Method code
private async Task ReadItemName(IDialogContext context, IAwaitable<true> result)
{
//
}
//Calling method: ReadItemName(context, true);
something like this but it does not accept true, but i want to pass iAwaitable type?
You can use AwaitableFromItem<T>:
ReadItemName(context, new AwaitableFromItem(true));
See doc here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.bot.builder.dialogs.awaitablefromitem-1?view=botbuilder-dotnet-3.0

C# - Using reflection with JsonSchema4.FromTypeAsync

[INTRO]
I know there are about a zillion QA about generics and reflections everywhere, but it's becoming a blackhole to me, and I'm only getting more lost the more I read!!
What i need to do is simple, and I'm amazed that it hasn't been addressed before.
[SAMPLE] Consider the following snippit:
public async Task<string> generateJsonSchema(string model)
{
try
{
string modelName = "Models." + model;
Type t = Type.GetType(modelName, false);
JsonSchema4 schema = await JsonSchema4.FromTypeAsync<t>();
return schema.ToJson();
}
catch (Exception ex)
{
Logger.WriteToLogFile(ex.ToString(), "exception");
return "";
}
}
[PROBLEM] Now the main problem is that variable t is evaluated at runtime, thus, JsonSchema4.FromTypeAsync<t>() throws the error 't' is a variable but is used like a type when trying to build compile time
Whoever used JsonSchema4 will understand what I'm trying to achieve here.
Instead of creating a generate function for each of my models, or make a switch/if-else logic,
[QUESTION]
How to make it receive the model name as a string parameter, and convert the string-model-name to model-type and pass it to jSonSchema4 method.
The problem here is that, as you say, t is evaluated as runtime.
I also ran into this Problem and solved it by creating a MethodInfo of the method I wanted to invoke, in your case JsonSchema4.FromTypeAsync<t>().
So basically this is want may fix the problem:
var methodInfo = typeof(JsonSchema4).GetMethod("FromTypeAsync", new Type[] { }); //Get the "normal method info", the overload without parameters
var methodInfoWithType = methodInfo.MakeGenericMethod(t); //now you have a method with your desired parameter t as TypeParameter
Task<JsonSchema4> task = methodInfoWithType.Invoke(null, null) as Task<JsonSchema4>; //now you can cast the result from invoke as Task to keep the Async-Await functionality
var schema = await task;
return schema.ToJson();

How does a lambda expression working in the given code snippet

I have the below code snippet in my project. I am new to lambda expressions. I have some idea about it and also
started using it. But I do not understand how the below code is working. Specially,
NotifyIntrenal( notification, callback, changedTypes => ..
Now here changedTypes is one of the parameter for method NotifyIntrenal. We derive its value using an anomymous method.
If I see the code, since I do not assign any value to changedTypes, so as per my understanding the code if (changedTypes == null) should
always be true. But this is not the case when I debug.
Can someone explain me how does this works here?
private void Notify( Notification notification )
{
var nameDto = GetNameDto();
foreach (var subscription in _subscriptionsDictionary)
{
var callback = subscription.Key;
var subscribedTypes = subscription.Value;
NotifyIntrenal( notification, callback, changedTypes =>
{
if (changedTypes == null)
return subscribedTypes;
if (!changedTypes.Any())
return subscribedTypes;
return changedTypes.Intersect(subscribedTypes);
}, nameDto);
}
}
Thanks & Regards
changedTypes is not an argument to NotifyInternal. It is the parameter for the anonymous method.
This whole method is the argument for NotifyInternal.
The code inside that lambda is not executed at this point. It will only be executed if some line in NotifyInternal calls it. So there has to be code line in NotifyInternal executing the anonymous method:
void NotifyInternal(Notification notification, Callback callback, Func<IEnumerable<Type>, IEnumerable<Type>> function, string nameDto)
{
// ... some code
// execute the lambda
var result = function(mychangedtypesvariable);
// ... more code
}
Only then the code inside the lambda is executed, using the pass argument (mychangedtypesvariable in that example). So if this will be null you cannot decide from the snippet you see.
changedTypes is just a paremeter for your anonymous method, not for NotifyIntrenal. The latter however calls that anonymous method and fills the parameter (if required) appropriately. In your case the anonymous method expects an IEnumerable<MyType> and returns an IEnumerable<MyType>.
NotifyIntrenal(string arg1, string arg2, Func<IEnumerable<MyType>, IEnumerable<MyType>> func) {
// do something
var list = new List<MyType> { ...}
// execute the delegate with the list
IEnumerable<MyType> result = func(list);
}
So actually changedTypes is provided by NotifyIntrenal, not given to it. How you create that argument within the method is up to you.

Pass argument to AsyncCallback function?

I'm learning socket programming and I have the following function:
public void OnDataReceived(IAsyncResult asyn)
and this is how the callback gets set:
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
The problem is I need to pass another argument to OnDataReceived callback function, how can I do this? I'm trying to make a simple tcp server and I need to track from which client the data is coming from. Any tips? Thanks!
I'm going to presume you're using System.Net.Sockets.Socket here. If you look at the overloads of BeginReceive you'll see the object parameter (named state). You can pass an arbitrary value as this parameter and it will flow through to your AsyncCallback call back. You can then acess it using the AsyncState property of IAsyncResult object passed into your callback. Eg;
public void SomeMethod() {
int myImportantVariable = 5;
System.Net.Sockets.Socket s;
s.BeginReceive(buffer, offset, size, SocketFlags.None, new new AsyncCallback(OnDataReceived), myImportantVariable);
}
private void OnDataReceived(IAsyncResult result) {
Console.WriteLine("My Important Variable was: {0}", result.AsyncState); // Prints 5
}
This is a problem I prefer to solve with anonymous delegates:
var someDataIdLikeToKeep = new object();
mySocket.BeginBlaBla(some, other, ar => {
mySocket.EndBlaBla(ar);
CallSomeFunc(someDataIdLikeToKeep);
}, null) //no longer passing state as we captured what we need in callback closure
It saves having to cast a state object in the receiving function.
When you call BeginReceive, you can pass any object as its last parameter. The same object will be made available to your callback through IAsyncResult's AsyncState property.
As MrMDavidson mentioned.
If you look at the overloads of BeginReceive you'll see the object parameter (named state)
You could pass an object array of your desired parameters to the state parameter and then deal with them later in the callback method.
client.BeginConnect(ipEndPoint, new AsyncCallback(ConnectedCallback), new object[] { parameter1, parameter2});

Categories