Refactor .Result with await in constructor - c#

I have a parent-child class structure where parent class in constructor creates instance of the child class and use one of child class async methods with .Result approach.
public class ParentClass
{
private readonly ChildClass _childClass;
public ParentClass()
{
_childClass = new ChildClass();
bool result = _childClass.GetSomething().Result;
}
}
public class ChildClass
{
public ChildClass()
{
}
public async Task<bool> GetSomething()
{
return await Task.FromResult<bool>(false);
}
}
My goal is to remove .Result and change it with normal await keyword. I can create static async method, there create instance of the child class, later call constructor and pass instance.
public class ParentClass2
{
private readonly ChildClass _childClass;
private ParentClass2(ChildClass childClass, bool result)
{
_childClass = childClass;
}
public static async Task<ParentClass2> GetInstance()
{
ChildClass childClass = new ChildClass();
bool result = await childClass.GetSomething();
return new ParentClass2(childClass, result);
}
}
But then I have 2 problems:
The more parents of parents [..of parents] I have - the more code I have to modify in a same way.
Highest level classes use DI. And with async I can't do this
services.AddScoped<ParentClass2>(async p =>
{
var instance = await ParentClass2.GetInstance();
return instance;
});
Any suggestions?

When you deal with dependency injection and asynchronous initialization, you have to make compromises.
In general, I approach this one of two ways.
If the asynchronous initialization is done once at startup, you can extract the asynchronous call out before the DI is set up, run it synchronously, and inject the results into the constructors for your types at DI setup.
The other option is to essentially do the asynchronous initialization on-demand whenever any other method is called. The constructor could start it, and every method would (asynchronously) wait for the initialization to complete. This does have the side effect that the entire API has to be asynchronous. Either that, or you change the DI type to be an asynchronous factory which then asynchronously creates the type with your actual API.

Related

C# Generic method calling two different services

I have the following method, which is to add product using the injected service! It is called inside a static calls hence it is static!
public static async Task AddNewProducts(Guid shopId)
{
var productAService = IoC.Services.GetService<IProductAService>();
var added = await productAService.AddProduct(shopId);
}
It works fine but I need to make it generic so that I can use different services with it.
Something like this!
public static async Task AddNewProducts<T>(Guid shopId)
where T : IProductAService, IProductBService
{
var productService = IoC.Services.GetService<T>();
var added = await productService.AddProduct(shopId);
}
However the second methods complains that the AddProduct method is ambiguous, not sure how I can make sure it is calling the right method from the related service!
Your 2 services need a common interface
public interface IProductService
{
void AddProduct(Guid shopId);
}
public interface IProductAService : IProductService
{
//specifics to service A
}
public interface IProductBService : IProductService
{
//specifics to service B
}
Then your static, generic method just constrains to the shared interface
public static async Task AddNewProducts<TProductService>(Guid shopId)
where TProductService : IProductService
{
var productService = IoC.Services.GetService<TProductService>();
await productService.AddProduct(shopId);
}
This gets slippery very quickly. You hinted that AddProduct is not a void, but returns a particular object. That's fine, you can make IProductService itself generic
public interface IProductService<TProduct>
{
TProduct AddProduct(Guid shopId);
}
public interface IProductAService : IProductService<ProductA>
{
//specifics to service A
}
public interface IProductBService : IProductService<ProductB>
{
//specifics to service B
}
But now you need to also pass the product type to the generic method, as I said - it gets slippery quickly (but maybe it'll do!)
public static async Task AddNewProducts<TProductService, TProduct>(Guid shopId)
where TProductService : IProductService<TProduct>
{
var productService = IoC.Services.GetService<TProductService<TProduct>>();
var added = await productService.AddProduct(shopId);
// Note "added" is of type TProduct
}
I call this situation "Generic hell". You are better of rethinking your design!
public static async Task AddNewProducts<T>(Guid shopId) where T : IProductAService, IProductBService
The problem with that line is that you're requiring T to implement both interfaces at once, not just one of them. You haven't even gotten to the errors that will spring up when you try to call this function, because presumably your class won't implement both.
Which leads me to question why you think you need to constrain your T like this. The only usage of T is to call Services.GetService<T>(), so the only constraint on it should be exactly the constraints that function requires, which are definitely not your two interfaces.

Long running initialisation of class fields in constructor

Say I have the class below
public class MyClass {
private readonly NinjaObject _myNinja;
MyClass(NinjaFactory ninjaFactory) {
_myNinja = ninjaFactory.CreateNinjaButItTakesTime();
}
public void NinjaAttack() {
_myNinja.Attack();
}
}
Now, the constructor should do everything to initialise the class and get it ready for use by the application, i.e., create the Ninja and have it ready to attack when called to do so. It's also a good idea to have your constructor perform their actions quickly. However, this may not be possible if the process of creating a Ninja takes a long time. I presume you could create the Ninja asynchronously through some kind of static factory method, but then you run the risk (at least theoretically) of the Ninja not being ready (i.e. a null object) to attack when called to do so by the application.
When you have fields of a class that are critical to how that class operates but can take a long time to construct, what is the best pattern to adopt in creating them? Keep it synchronous in the constructor, or apply some kind of asynchronous pattern?
I presume you could create the Ninja asynchronously through some kind of static factory method, but then you run the risk (at least theoretically) of the Ninja not being ready (i.e. a null object) to attack when called to do so by the application.
Well, this is where an async static factory method comes in handy:
public class MyClass
{
private readonly Ninja ninja;
private MyClass(Ninja ninja)
{
this.ninja = ninja;
}
public static async Task<MyClass> Create()
{
// Or however you create a ninja - ideally properly asynchronous
var ninja = await Ninja.Create();
return new MyClass(ninja);
}
public void NinjaAttack() => ninja.Attack();
}
You can't avoid it taking a long time - but you can make the creation asynchronous by leaving the constructor call right to the end. This basically works around the restriction that constructors can't be asynchronous.
An alternative - but a dangerous one - would be to start the task creating the ninja and pass that into the constructor, but use the result of the task later:
public class MyClass
{
private readonly Task<Ninja> ninjaTask;
public MyClass(Task<Ninja> ninjaTask)
{
this.ninjaTask = ninjaTask;
}
public void NinjaAttack() => ninjaTask.Result.Attack();
}
That's dangerous because using Task<T>.Result can deadlock in some cases, if the task needs to do more work in the current synchronization context before completing. You could avoid that by making your NinjaAttack method asynchronous instead:
public class MyClass
{
private readonly Task<Ninja> ninjaTask;
public MyClass(Task<Ninja> ninjaTask)
{
this.ninjaTask = ninjaTask;
}
public async Task NinjaAttack() => (await ninjaTask).Attack();
}
Depending on your context, you might want to use await ninjaTask.ConfigureAwait(false).

Forcing a syncronous reactive extension call

I am working on some code which looks something like this:
public class ManagerViewModel : ManagerViewModelBase
{
public ManagerViewModel(ISettingsProvider settingsProvider):
base(settingsProvider.Settings)
}
public class ManagerViewModelBase
{
private IEnumerable<string> _mySettings = Enumerable.Empty<string>();
public ManagerViewModelBase(IEnumerable<string> settings)
{
_mySettings = settings;
}
}
ISettingsProvider is provided via Unity and looks like:
public class SettingsProvider : ISettingsProvider
{
private readonly Service _service;
IEnumerable<string> _settings = Enumerable.Empty<string>();
public IEnumerable<string> Settings {get {return _settings}};
public SettingsProvider (
IService _service,
ISettingsProvider settingsProvider)
{
_service = service;
LoadSettings();
}
private void LoadSettings()
{
//_service just supplies the data
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}
private void LoadSettingsCompleted(IEnumerable<string> settings)
{
_settings = settings;
}
}
The issue is that when SettingsProvider is instantiated, it may take a little time to get the results from the service call and as a result, before the call is completed and _settings populated, the base(settingsProvider.Settings) call is made, basically passing on an empty enumerable.
Is there a way I can make the SettingsProvider.Settings property call wait until the data from the Service.GetSettings call is available, and timeout after a certain amount of time? I guess I am looking for the simplest way to block on that property call.
Thanks.
I realized your question is how to wait/block, but I must tell you that you probably shouldn't. Likely your ViewModel is getting created in the UI thread, and blocking is the last thing you want in there.
If your ViewModel relies on something asynchronous, then its creation is asynchronous, and you should hide that with the wait.
Async in constructor can't be used, but alternatively you can make your VM constructor private, and expose an async static factory method instead, something like:
private ManagerViewModel(IEnumerable<string> settings) : base(settings) {}
public async Task<ManagerViewModel> CreateAsync(ISettingsProvider settingsProvider) {
var settings = await settingsProvider.GetSettingsAsync();
return new ManagerViewModel(settings);
}
// ....
public async Task<IEnumerable<Settings>> GetSettingsAsync() {
return await _service.GetSettings().Timeout(...).FirstAsync();
}
Expose async all the way and never block would be my recommandation.
None of this is very reactive but you could block using the Observable.FirstAsync() and Observable.Wait() extension methods. So your LoadSettings() method could look something like:
private void LoadSettings()
{
_settings = _service.GetSettings
.Timeout(_expireTime, Observable.Return(Enumerable.Empty<string>()))
.FirstAsync()
.Wait();
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}

Calling functions on intercepted method invocations in Simple Injector

What I am trying to achieve is to intercept the injection of a class, and call a specific method on the class to alter it's behaviour.
I have implemented the interceptor class that is given on the SimpleInjector website, and this is working, so I am able to get some functionality running when the class is intercepted.
My container is registering it as such:
container.InterceptWith<MyInterceptor>(type => type == typeof(IMyClass));
The class I am intercepting on looks as such:
public class MyClass : IMyClass
{
private IAnotherClass m_class;
public MyClass(IAnotherClass _class)
{
m_class = _class;
}
public void MethodToCall()
{
//changes properties on class
}
}
My interceptor class looks as such:
public class MyInterceptor : IInterceptor
{
private readonly ILogger logger;
public MyInterceptor(ILogger logger)
{
this.logger = logger;
}
public void Intercept(IInvocation invocation)
{
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var decoratedType = invocation.InvocationTarget.GetType();
logger.Trace(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedTicks));
}
}
What I am trying to achieve is to call a method on the intercepted IMyClass. So in the interceptor, call MyClass.MethodToCall()
I have tried to do something like this in the Intercept() method:
var classIntercepted = invocation.ReturnValue;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("MethodToCall");
object magicValue = method.Invoke(classIntercepted, null);
But, the invocation.ReturnValue is not returning the MyClass instance, but rather the IAnotherClass instance
Why don't you use a decorator instead of using interception? This is often much easier, more maintainable and faster.
Here's an example:
public class PropSetMyClassDecorator : IMyClass
{
private MyClass decoratee;
public PropSetMyClassDecorator(MyClass decoratee) {
this.decoratee = decoratee;
}
public void MethodToCall() {
this.decoratee.SetConnectionString();
this.decoratee.MethodToCall();
}
}
You can register this decorator as follows:
container.Register<IMyClass, PropSetMyClassDecorator>();
Do note that instead of registering MyClass, we only register the decorator. Since the decorator directly depends on MyClass (not on the interface) MyClass will be automatically resolved by Simple Injector.
Yet another option is to register an initializer as follows:
container.RegisterInitializer<MyClass>(instance => {
instance.SetConnectionString();
});
The initializer delegate will be called every time after a MyClass instance is constructed. The behavior is a bit different in this case, since the method isn't called every time, but only during construction. Usually however, this should be sufficient, since you should normally not change a service during runtime, since you are complicating things.
Ok, found a solution fairly shortly after posting the question.
I changed my Intercept function to be the following:
public void Intercept(IInvocation invocation)
{
// Calls the decorated instance.
invocation.Proceed();
var classIntercepted = invocation.InvocationTarget;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("SetConnectionString");
method.Invoke(classIntercepted, null);
}

Can constructors be async?

I have a project where I'm trying to populate some data in a constructor:
public class ViewModel
{
public ObservableCollection<TData> Data { get; set; }
async public ViewModel()
{
Data = await GetDataTask();
}
public Task<ObservableCollection<TData>> GetDataTask()
{
Task<ObservableCollection<TData>> task;
//Create a task which represents getting the data
return task;
}
}
Unfortunately, I'm getting an error:
The modifier async is not valid for this item
Of course, if I wrap in a standard method and call that from the constructor:
public async void Foo()
{
Data = await GetDataTask();
}
it works fine. Likewise, if I use the old inside-out way
GetData().ContinueWith(t => Data = t.Result);
That works too. I was just wondering why we can't call await from within a constructor directly. There are probably lots of (even obvious) edge cases and reasons against it, I just can't think of any. I've also search around for an explanation, but can't seem to find any.
Since it is not possible to make an async constructor, I use a static async method that returns a class instance created by a private constructor. This is not elegant but it works ok.
public class ViewModel
{
public ObservableCollection<TData> Data { get; set; }
//static async method that behave like a constructor
async public static Task<ViewModel> BuildViewModelAsync()
{
ObservableCollection<TData> tmpData = await GetDataTask();
return new ViewModel(tmpData);
}
// private constructor called by the async method
private ViewModel(ObservableCollection<TData> Data)
{
this.Data = Data;
}
}
Constructor acts very similarly to a method returning the constructed type. And async method can't return just any type, it has to be either “fire and forget” void, or Task.
If the constructor of type T actually returned Task<T>, that would be very confusing, I think.
If the async constructor behaved the same way as an async void method, that kind of breaks what constructor is meant to be. After constructor returns, you should get a fully initialized object. Not an object that will be actually properly initialized at some undefined point in the future. That is, if you're lucky and the async initialization doesn't fail.
All this is just a guess. But it seems to me that having the possibility of an async constructor brings more trouble than it's worth.
If you actually want the “fire and forget” semantics of async void methods (which should be avoided, if possible), you can easily encapsulate all the code in an async void method and call that from your constructor, as you mentioned in the question.
Your problem is comparable to the creation of a file object and opening the file. In fact there are a lot of classes where you have to perform two steps before you can actually use the object: create + Initialize (often called something similar to Open).
The advantage of this is that the constructor can be lightweight. If desired, you can change some properties before actually initializing the object. When all properties are set, the Initialize/Open function is called to prepare the object to be used. This Initialize function can be async.
The disadvantage is that you have to trust the user of your class that he will call Initialize() before he uses any other function of your class. In fact if you want to make your class full proof (fool proof?) you have to check in every function that the Initialize() has been called.
The pattern to make this easier is to declare the constructor private and make a public static function that will construct the object and call Initialize() before returning the constructed object. This way you'll know that everyone who has access to the object has used the Initialize function.
The example shows a class that mimics your desired async constructor
public MyClass
{
public static async Task<MyClass> CreateAsync(...)
{
MyClass x = new MyClass();
await x.InitializeAsync(...)
return x;
}
// make sure no one but the Create function can call the constructor:
private MyClass(){}
private async Task InitializeAsync(...)
{
// do the async things you wanted to do in your async constructor
}
public async Task<int> OtherFunctionAsync(int a, int b)
{
return await ... // return something useful
}
Usage will be as follows:
public async Task<int> SomethingAsync()
{
// Create and initialize a MyClass object
MyClass myObject = await MyClass.CreateAsync(...);
// use the created object:
return await myObject.OtherFunctionAsync(4, 7);
}
if you make constructor asynchronous, after creating an object, you may fall into problems like null values instead of instance objects. For instance;
MyClass instance = new MyClass();
instance.Foo(); // null exception here
That's why they don't allow this i guess.
In this particular case, a viewModel is required to launch the task and notify the view upon its completion. An "async property", not an "async constructor", is in order.
I just released AsyncMVVM, which solves exactly this problem (among others). Should you use it, your ViewModel would become:
public class ViewModel : AsyncBindableBase
{
public ObservableCollection<TData> Data
{
get { return Property.Get(GetDataAsync); }
}
private Task<ObservableCollection<TData>> GetDataAsync()
{
//Get the data asynchronously
}
}
Strangely enough, Silverlight is supported. :)
I was just wondering why we can't call await from within a constructor directly.
I believe the short answer is simply: Because the .Net team has not programmed this feature.
I believe with the right syntax this could be implemented and shouldn't be too confusing or error prone. I think Stephen Cleary's blog post and several other answers here have implicitly pointed out that there is no fundamental reason against it, and more than that - solved that lack with workarounds. The existence of these relatively simple workarounds is probably one of the reasons why this feature has not (yet) been implemented.
calling async in constructor maybe cause deadlock, please refer to
http://social.msdn.microsoft.com/Forums/en/winappswithcsharp/thread/0d24419e-36ad-4157-abb5-3d9e6c5dacf1
http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx
Some of the answers involve creating a new public method. Without doing this, use the Lazy<T> class:
public class ViewModel
{
private Lazy<ObservableCollection<TData>> Data;
async public ViewModel()
{
Data = new Lazy<ObservableCollection<TData>>(GetDataTask);
}
public ObservableCollection<TData> GetDataTask()
{
Task<ObservableCollection<TData>> task;
//Create a task which represents getting the data
return task.GetAwaiter().GetResult();
}
}
To use Data, use Data.Value.
C# doesn't allow async constructors. Constructors are meant to return fast after some brief initialization. You don't expect and you don't want to wait for an instance i.e. the constructor to return. Therefore, even if async constructors were possible, a constructor is not a place for long-running operations or starting background threads. The only purpose of a constructor is initialization of instance or class members to a default value or the captured constructor parameters. You always create the instance and then call DoSomething() on this instance. Async operations are no exception. You always defer expensive initialization of members.
There are a few solutions to avoid the requirement of async constructors.
A simple alternative solution using Lazy<T> or AsyncLazy<T> (requires to install the Microsoft.VisualStudio.Threading package via the NuGet Package Manager). Lazy<T> allows to defer the instantiation or allocation of expensive resources.
public class OrderService
{
public List<object> Orders => this.OrdersInitializer.GetValue();
private AsyncLazy<List<object>> OrdersInitializer { get; }
public OrderService()
=> this.OrdersInitializer = new AsyncLazy<List<object>>(InitializeOrdersAsync, new JoinableTaskFactory(new JoinableTaskContext()));
private async Task<List<object>> InitializeOrdersAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return new List<object> { 1, 2, 3 };
}
}
public static void Main()
{
var orderService = new OrderService();
// Trigger async initialization
orderService.Orders.Add(4);
}
You can expose the data using a method instead of a property
public class OrderService
{
private List<object> Orders { get; set; }
public async Task<List<object>> GetOrdersAsync()
{
if (this.Orders == null)
{
await Task.Delay(TimeSpan.FromSeconds(5));
this.Orders = new List<object> { 1, 2, 3 };
}
return this.Orders;
}
}
public static async Task Main()
{
var orderService = new OrderService();
// Trigger async initialization
List<object> orders = await orderService.GetOrdersAsync();
}
Use an InitializeAsync method that must be called before using the instance
public class OrderService
{
private List<object> orders;
public List<object> Orders
{
get
{
if (!this.IsInitialized)
{
throw new InvalidOperationException();
}
return this.orders;
}
private set
{
this.orders = value;
}
}
public bool IsInitialized { get; private set; }
public async Task<List<object>> InitializeAsync()
{
if (this.IsInitialized)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(5));
this.Orders = new List<object> { 1, 2, 3 };
this.IsInitialized = true;
}
}
public static async Task Main()
{
var orderService = new OrderService();
// Trigger async initialization
await orderService.InitializeAsync();
}
Instantiate the instance by passing the expensive arguments to the constructor
public class OrderService
{
public List<object> Orders { get; }
public async Task<List<object>> OrderService(List<object> orders)
=> this.Orders = orders;
}
public static async Task Main()
{
List<object> orders = await GetOrdersAsync();
// Instantiate with the result of the async operation
var orderService = new OrderService(orders);
}
private static async Task<List<object>> GetOrdersAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return new List<object> { 1, 2, 3 };
}
Use a factory method and a private constructor
public class OrderService
{
public List<object> Orders { get; set; }
private OrderServiceBase()
=> this.Orders = new List<object>();
public static async Task<OrderService> CreateInstanceAsync()
{
var instance = new OrderService();
await Task.Delay(TimeSpan.FromSeconds(5));
instance.Orders = new List<object> { 1, 2, 3 };
return instance;
}
}
public static async Task Main()
{
// Trigger async initialization
OrderService orderService = await OrderService.CreateInstanceAsync();
}
you can use Action inside Constructor
public class ViewModel
{
public ObservableCollection<TData> Data { get; set; }
public ViewModel()
{
new Action(async () =>
{
Data = await GetDataTask();
}).Invoke();
}
public Task<ObservableCollection<TData>> GetDataTask()
{
Task<ObservableCollection<TData>> task;
//Create a task which represents getting the data
return task;
}
}
you can create a wrapper and inject a functor representing the constructor:
class AsyncConstruct<T>
where T: class
{
private readonly Task<T> m_construction;
private T m_constructed;
public AsyncConstruct(Func<T> createFunc)
{
m_constructed = null;
m_construction = Task.Run(()=>createFunc());
}
public T Get()
{
if(m_constructed == null)
{
m_constructed = m_construction.Result;
}
return m_constructed;
}
}
Please bump this language request:
https://github.com/dotnet/csharplang/discussions/419
The amount of boilerplate code everyone needs to write to have a fully initialized async object is crazy and completely opposite of the trend in C# (less boilerplate).
I would use something like this.
public class MyViewModel
{
public MyDataTable Data { get; set; }
public MyViewModel()
{
loadData(() => GetData());
}
private async void loadData(Func<DataTable> load)
{
try
{
MyDataTable = await Task.Run(load);
}
catch (Exception ex)
{
//log
}
}
private DataTable GetData()
{
DataTable data;
// get data and return
return data;
}
}
This is as close to I can get for constructors.
I use this easy trick.
public sealed partial class NamePage
{
private readonly Task _initializingTask;
public NamePage()
{
_initializingTask = Init();
}
private async Task Init()
{
/*
Initialization that you need with await/async stuff allowed
*/
}
}
I'm not familiar with the async keyword (is this specific to Silverlight or a new feature in the beta version of Visual Studio?), but I think I can give you an idea of why you can't do this.
If I do:
var o = new MyObject();
MessageBox(o.SomeProperty.ToString());
o may not be done initializing before the next line of code runs. An instantiation of your object cannot be assigned until your constructor is completed, and making the constructor asynchronous wouldn't change that so what would be the point? However, you could call an asynchronous method from your constructor and then your constructor could complete and you would get your instantiation while the async method is still doing whatever it needs to do to setup your object.

Categories

Resources