Async ObservableCollection from Interface in C# (Xamarin) - c#

I've got an ObservableCollection in an interface and I'm using it with a RestApi-Request. It has some Await functions and it must be async. But there's an error.
Here's the interface:
public interface IDbConnection
{
ObservableCollection<Einkauf> GetEinkauf();
}
Here's the part from the class it is using:
public partial class RestView : IDbConnection
{
private ObservableCollection<Einkauf> _einkauf;
private const string Url = "http://localhost:3003/einkauf";
private HttpClient _client = new HttpClient();
public RestView ()
{
InitializeComponent ();
}
public async ObservableCollection<Einkauf> GetEinkauf()
{
var content = await _client.GetStringAsync(Url);
var einkauf = JsonConvert.DeserializeObject<List<Einkauf>>(content);
_einkauf = new ObservableCollection<Einkauf>(einkauf);
speisenListe.ItemsSource = _einkauf;
return _einkauf;
}
}
The GetEinkauf is underlined and it says:
CS1983 C# The return type of an async method must be void, Task or Task<T>
Does anybody know how to fix this?

public interface IDbConnection
{
Task<ObservableCollection<Einkauf>> GetEinkauf();
}
public async Task<ObservableCollection<Einkauf>> GetEinkauf()
{
...
}

If GetEinkauf is supposed to be implemented as an asynchronous method, you should change it return type to Task<ObservableCollection<Einkauf>> and also change its name to GetEinkaufAsync to follow the naming convention for asynchronous methods:
public interface IDbConnection
{
Task<ObservableCollection<Einkauf>> GetEinkaufAsync();
}
public async Task<ObservableCollection<Einkauf>> GetEinkaufAsync()
{
var content = await _client.GetStringAsync(Url);
var einkauf = JsonConvert.DeserializeObject<List<Einkauf>>(content);
_einkauf = new ObservableCollection<Einkauf>(einkauf);
speisenListe.ItemsSource = _einkauf;
return _einkauf;
}
You could then await the method from any method marked as async:
var collection = await GetEinkaufAsync();
If another class implements the IDbConnection interface in a synchronous fashion for some reason, it could use the Task.FromResult method to return a Task<ObservableCollection<Einkauf>>:
public class SomeOtherClass : IDbConnection
{
public Task<ObservableCollection<Einkauf>> GetEinkaufAsync()
{
return Task.FromResult(new ObservableCollection<Einkauf>());
}
}

Related

How to execute a default method before the interface implementation code C#?

I have an interface which implements only one method:
public interface IHandler<T> where T : Comand
{
Task<IResultComand> HandlerAsync(T comand);
}
And I use it in my classes as follows:
public class ProductHandler : IHandler<NewProductComand>,
IHandler<EditProductComand>,
IHandler<DeleteProductComand>
public async Task<IResultComand> HandlerAsync(NewProductComand comand)
{
ResultComand result = new();
comand.Validate();
if (!comand.Valid)
{
return result;
}
//Create new product
return result;
}
public async Task<IResultComand> HandlerAsync(EditProductComand comand)
{
ResultComand result = new();
comand.Validate();
if (!comand.Valid)
{
return result;
}
//Edit product
return result;
}
public async Task<IResultComand> HandlerAsync(DeleteProductComand comand)
{
ResultComand result = new();
comand.Validate();
if (!comand.Valid)
{
return result;
}
//Delete product
return result;
}
And my Comand has the following code:
public abstract class Comand
{
public bool Valid { get; set; }
public abstract void Validate();
}
How to make the following code run implicitly before executing the implementation code in HandlerAsync? (Some thing like a ActionFilter Web API .NET)
ResultComand result = new();
comand.Validate();
if (!comand.Valid)
{
return result;
}
You're looking for the Decorator Pattern.
Basically, you leave your 'base' CommandHandler as it is and let it do its job, but you add an additional class that implements the same interface:
ExtraStuffCommandHandlerDecorator<TComand> : IHandler<TComand>
where TComand : Comand
{
readonly IHandler<TComand> _decorated;
public ExtraStuffCommandHandlerDecorator(IHandler<TComand> decorated)
{
_decorated = decorated;
}
public async Task<IResultComand> HandlerAsync(TComand comand)
{
// Do stuff before base command execution
IResultComand result = await _decorated.HandlerAsync(comand);
// Do stuff after base command execution
return result;
}
}
Now your mediator that is currently instantiating and calling the base handler directly, should instead look up the decorator and call that instead, passing the base handler in as a constructor argument.
Using decorators is well supported by Autofac's RegisterGenericDecorator method. Implementation with Asp Core DI is a little more complex, but here's a guide.
https://andrewlock.net/adding-decorated-classes-to-the-asp.net-core-di-container-using-scrutor/#manually-creating-decorators-with-the-asp-net-core-di-container

Make ProcessCmdKey async await - C# [duplicate]

I am overriding a method in a base class library. However, inside my overridden implementation I am using the new HttpClient which is all based on async methods. I therefore have to mark my method as async, which means that I need to change the return parameter of the method from string to Task. The compiler however gives an error: "The return type must be 'string' to match overridden member ...."
public class BaseClass
{
public virtual string GetName()
{
...
}
}
public class MyClass : BaseClass
{
public override async Task<string> GetName()
{
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync("");
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
return await responseContent.ReadAsStringAsync();
}
return null;
}
}
Of course the obvious solution would be to change the return type of GetName() in BaseClass to Task<string>, but I have no control over BaseClass as it is an external library;
My current solution is to use the HttpClient classes in a synchronous fashion, i.e. change MyClass as follows:
public class MyClass : BaseClass
{
public override string GetName()
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync("");
if (response.Result.IsSuccessStatusCode)
{
var responseContent = response.Result.Content;
return responseContent.ReadAsStringAsync()
.Result;
}
return null;
}
}
Is there any other way to do this?
Unfortunately there isn't a good solution here. There is no way to override a non-async method with an async one. I think your best bet is to have an async non-override method and call into that from the non-async one:
public class MyClass : BaseClass
{
public override string GetName()
{
return GetNameAsync().Value;
}
public async Task<string> GetNameAsync()
{
...
}
}
Note that this can cause problems though. If the original code didn't expect for any async code to be executing introducing this pattern could break expectations. I would avoid it if possible.
Luckily the ReadAsStringAsync().Result is not causing a deadlock since it is likely to have ConfigureAwait(false) within.
To prevent a deadlock, you could use one of the following methods:
public static T GetResult<T>(Func<Task<T>> func)
{
var httpContext = HttpContext.Context;
var proxyTask = Task.Run(() =>
{
HttpContext.Context = httpContext;
return func();
});
return proxyTask.Result;
}
// or
public static T GetResult<T>(Func<Task<T>> func)
{
var syncContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
var task = func();
SynchronizationContext.SetSynchronizationContext(syncContext);
return task.Result;
}
This way you would call
public override string GetName()
{
...
return GetResult(() => responseContent.ReadAsStringAsync());
...
}
The former has a performance overhead by spawning a new thread, while the latter suffers from breaking SynchronizationContext flow, which makes any context bound to it unavailable in the task being called, e.g. HttpContext.Current.
I've also had this problem, and the solution was using an interface, in which 'async' isn't part of the method's signature.
public abstract class Base : IInvokable {
/* Other properties ... */
public virtual async Task Invoke() {
/*...*/
}
}
public interface IInvokable {
Task Invoke();
}
public class Derived
{
public override async Task Invoke() {
// Your code here
}
}

Success/Failure return type for Generic Method

I have wrote Generic Methods for Get,Post and Put. An example of Get Generic Method is :
public async Task<object> GetAsync<T>(string uri, NamingStrategy namingStrategy)
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri))
{
return await ProcessAsync<T>(requestMessage, namingStrategy);
}
}
and ProcessAync is :
public async Task<object> ProcessAsync<T>(HttpRequestMessage request, NamingStrategy namingStrategy)
{
if (!string.IsNullOrEmpty(AuthToken))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
}
HttpResponseMessage response = await _client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Request Succeeded");
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = namingStrategy
}
};
T responseModel = JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync(), dezerializerSettings);
return responseModel;
}
else
{
return await GetFailureResponseModel(response);
}
}
than i am calling this get method like that in my SingletonClass
public async Task<object> GetShops(string category)
{
_logger.LogInformation("ClubMatas outgoing request: {RequestName}", nameof(GetShops));
return await _client.GetAsync<ShopsResponseModel>($"v2/shops?category={WebUtility.UrlEncode(category)}");
}
And this method is called in my Controller like this
public async Task<ActionResult<object>> GetShops([FromQuery(Name = "category")]string category)
{
var response = await _httpClient.GetShops(category);
return ParseResponse<ShopsResponseModel>(response);
}
and ParseResponse is
protected ActionResult<object> ParseResponse<T>(object response)
{
if (response.GetType() == typeof(T))
{
return Ok(response);
}
else
{
return Error(response);
}
}
As the call chain shows, I am expecting other SuccessModel or FailureModel in my Api response and due to that I have to use object as return type. But I have feeling that I shouldn't be using object type for return. FYI above chain works fine. I am just looking for more refactoring or enhancement of my current flow. looking for more elegant solution to this problem. Please do suggest any other solution for my problem.
Update
I tried #ChrisPratt suggestion of using Interface, but that solution is not working or maybe i am doing it wrong. So i created this empty Interface
public interface IResult
{
}
And I extended Both my ShopResponseModel and FailureResponseModel from IResult Interface, and updated methods like this.
public async Task<IResult> GetShops(string category)
{
_logger.LogInformation("ClubMatas outgoing request: {RequestName}", nameof(GetShops));
return await _client.GetAsync<IResult>($"v2/shops?category={WebUtility.UrlEncode(category)}");
}
and
public async Task<T> GetAsync<T>(string uri, NamingStrategy namingStrategy)
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri))
{
return await ProcessAsync<T>(requestMessage, namingStrategy);
}
}
and I updated ProcessAsync return type from object to T. But getting errors.
But I have feeling that I shouldn't be using object type for return.
Yes. Don't use object for return values. It's virtually useless as a return type. What you should be doing is returning an interface. For example, you can do something like:
public interface IResponseStatusModel
{
bool Succeeded { get; }
int StatusCode { get; }
// etc.
}
Then:
public class SuccessModel : IResponseStatusModel
public class FailureModel : IResponseStatusModel
Then, you can return IResponseStatusModel, and based on the interface, you'll be able to interact with any property or method defined on the interface, regardless of which model you actually return.
However, you really shouldn't have separate classes for success/failure. Creating an interface that can generically allow you to interact with either one is going to lead to blurring the lines between the two, anyways. Instead, you should simply return a single model type, that has properties like the above and maybe a list property for errors and such. For example:
public class ProcessResult
{
public ProcessResult(int statusCode) : this(statusCode, null) {}
public ProcessResult(int statusCode, IEnumerable<string> errors)
{
Succeeded = statusCode < 300;
StatusCode = statusCode;
Errors = errors;
}
public bool Succeeded { get; private set; }
public int StatusCode { get; private set; }
public IEnumerable<string> Errors { get; private set; }
}
That's a very basic example. You might want to build it out more and provide a more robust solution for determining whether the task succeeded or not. The general idea is that you provide as much relevant information as possible concerning the result of the operation. Then, in your code, you can simply branch on Succeeded and then handle the situation accordingly:
if (result.Succeeded)
{
// do something on success
}
else
{
// do something on failure
}

using a generic method when using interface

Im stuck on a generics issue.
I have a method that returns DbSet from a DbContext object based on the object type.
Now I want to write I method where I pass in a object that implements a interface called IBaseData (that all entities implements). I want to use the existing method to return the correct DbSet based on the type of the IBaseData object, but I can't get it to work.
I've tried various versions of , typeof and gettype.
Existing method:
public GenericRepository<T> GetRepo<T>() where T : class
{
return new GenericRepository<T>(_context);
}
New method (this is just what Im trying to do):
public async Task SetDateLastInvoked<T>(IBaseData data, int id)
{
var tmp = GetRepo<typeof(data)>().Where(obj => obj.Id.Equals(id));
tmp.DateLastInvoked = DateTime.Now;
await SaveChangesAsync();
}
I assume you are doing something like:
public interface IBaseData
{
int Id { get; set; }
}
Then a method would looe like
public GenericRepository<T> GetRepo<T>()
where T : class
{
return new GenericRepository<T>(_context);
}
public async Task SetDateLastInvoked<T>(int id)
where T : class, IBaseData
{
var tmp = GetRepo<T>().FirstOrDefault(obj => obj.Id == id));
tmp.DateLastInvoked = DateTime.Now;
await SaveChangesAsync();
}
Usage:
public MyClass : IBaseData
{
public Id { get; set }
}
SetDateLastInvoked<MyClass>(1);
Ended up with this, based on previous answer:
public async Task SetLastInvoked<T>(int id) where T : class, IBaseData
{
var tmp = await GetRepo<T>().Single(obj => obj.Id.Equals(id));
tmp.DateLastInvoked = DateTime.Now;
await SaveChangesAsync();
}
I also created another method based on the same pattern:
public async Task DeleteItem<T>(int id, bool removeRow) where T : class, IBaseData
{
if (removeRow)
{
GetRepo<T>().Delete(await GetRepo<T>().Single(obj => obj.Id.Equals(id)));
}
else
{
var tmp = await GetRepo<T>().Single(obj => obj.Id.Equals(id));
tmp.Active = false;
}
await SaveChangesAsync();
}

ContextBoundObject with Async/Await

I have a system which uses AOP with ContextBoundObject.
This is used to intercept a method call and perform certain operations before and after the function. It all works fine until I make the 'function to be intercepted' async.
I understand that the C# compiler rewrites async methods into a state machine, which returns control to the sink as soon as 'await' is reached
So it continues into the interception and executes the code which is meant to be executed only after the Method.
I can see there is an "AsyncProcessMessage" in IMessageSink, but I can't find a way to invoke it, and I am not sure if it will work in the async/await scenario.
Is there a way to make Async/Await work with the ContextBoundObject? Is using another Aspect Oriented Programming approach the only option here?
The code sample below has the method to be intercepted decorated with the 'Audit' attribute and placed in the AuditFacade which is a ContextBoundObject. The SyncProcessMessage method in the AuditSink has the logic to be executed before and after the method.
[AuditBoundary]
public class AuditFacade : ContextBoundObject
{
[Audit]
public ResponseObject DoSomthing()
{
//Do something
return new ResponseObject();
}
/// <summary>
/// Async Method to be intercepted
/// </summary>
/// <returns></returns>
[Audit]
public async Task<ResponseObject> DoSomthingAysnc()
{
//Do something Async
await Task.Delay(10000);
return new ResponseObject();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class AuditAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class AuditBoundaryAttribute : ContextAttribute
{
public AuditBoundaryAttribute()
: base("AuditBoundary" + Guid.NewGuid().ToString())
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new AuditProperty());
}
}
public class AuditProperty : IContextProperty, IContributeObjectSink
{
public string Name
{
get { return "AuditProperty"; }
}
public bool IsNewContextOK(Context newCtx)
{
var p = newCtx.GetProperty("AuditProperty") as AuditProperty;
if (p == null)
return false;
return true;
}
public void Freeze(Context newContext)
{
}
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
return new AuditSink(nextSink);
}
}
public class AuditSink : IMessageSink
{
private IMessageSink nextSink;
public AuditSink(IMessageSink nextSink)
{
this.nextSink = nextSink;
}
public IMessage SyncProcessMessage(IMessage msg)
{
var message = msg as IMethodCallMessage;
IMethodReturnMessage returnMessage = null;
ResponseObject response;
//Some Pre Processing happens here
var newMessage = new MethodCallMessageWrapper(message);
//Invoke the Method to be Audited
returnMessage = nextSink.SyncProcessMessage(newMessage) as IMethodReturnMessage;
response = returnMessage.ReturnValue as ResponseObject;
//Some Post Processing happens here with the "response"
return returnMessage;
}
public IMessageSink NextSink
{
get { return this.nextSink; }
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return nextSink.AsyncProcessMessage(msg, replySink);
}
}
I don't know anything about ContextBoundObject, but I think that AsyncProcessMessage() has nothing to do with async-await and that the following should work using the normal SyncProcessMessage():
Do your preprocessing step.
Invoke the async method.
Add your postprocessing step as a continuation to the returned Task, using ContinueWith() or await.
Return the continuation Task to the caller.
If you're okay with your postprocessing executing on the thread pool, then ContinueWith() is probably simpler. If you need the postprocessing to execute on the original context, use await.
The await version could look like this:
var responseTask = (Task<ResponseObject>)returnMessage.ReturnValue;
Func<Task<ResponseObject>> postProcessTaskFunc = async () =>
{
var response = await responseTask;
// Some Post Processing happens here with the "response"
return response;
}
return new ReturnMessage(postProcessTaskFunc(), …);

Categories

Resources