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.
I am trying to run non static method from static and use dependency Injection inside non static method. (I am trying to do this inside one class)
My code looks like this:
public class Tokens
{
private IRefreshTokenRepository refreshTokenRepository;
public Tokens(IRefreshTokenRepository refreshTokenRepository)
{
this.refreshTokenRepository = refreshTokenRepository;
}
// I understand that problem is there, but I should to write this
//constructor because otherwise I can not use class variable in static method
public Tokens()
{
}
public static async Task<string> GenerateJwt()
{
RefreshToken rf = new RefreshToken{...};
Tokens t = new Tokens();
t.StoreRefToken(rf);
return JsonConvert.SerializeObject(...);
}
public async void StoreRefToken(RefreshToken reft)
{
this.refreshTokenRepository.InsertRefreshToken(reft);
await refreshTokenRepository.SaveAsync();
}
}
As you understand from code, when I wrote "Tokens t = new Tokens();" this code had used constructor without importing repository. What to do? Can I fix it inside single class?
Thank you
P.S. if question is silly I'm sorry
Static and Dependency Injection do not play well together.
Keep Tokens as an instance class and abstract it
public interface ITokenService {
Task<string> GenerateJwt();
}
so that it can be injected as a dependency.
derive Tokens from the abstraction
public class Tokens: ITokensService {
private readonly IRefreshTokenRepository refreshTokenRepository;
public Tokens(IRefreshTokenRepository refreshTokenRepository) {
this.refreshTokenRepository = refreshTokenRepository;
}
public async Task<string> GenerateJwt() {
RefreshToken rf = new RefreshToken{...};
await StoreRefToken(rf);
return JsonConvert.SerializeObject(...);
}
private async Task StoreRefToken(RefreshToken reft) {
this.refreshTokenRepository.InsertRefreshToken(reft);
await refreshTokenRepository.SaveAsync();
}
}
Now you have access to the desired members where ever it is needed as a dependency
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);
}
I was just finishing my new app, but I got stuck. My app is divided into 2 parts - remote and local. What I need is to register a class for interface based on some async deserialized application settings. Here is the 'idea code'
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// It can't work :(((
if(await SettingsManager.LoadSettings().EnableRemote) // <<<<<<
{
SimpleIoc.Default.Register<IMyService, MyRemoteService>();
}
else
{
SimpleIoc.Default.Register<IMyService, MyLocalService>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SomeOtherViewModel>();
}
How could I solve it? The settings are serialized in an XML file in Isolated Storage of my WinRT app. Please, can you think of any suggestions?
It sort of breaks the IoC pattern to register bindings asynchronously. You'll need to incorporate the async settings into a wrapper class. This wrapper class should be responsible for:
loading the settings
providing the actual implementation of IMyService
If IMyService has synchronous methods, then you'll probably have to change it, either to provide async versions of all the methods, or to provide a Ready property + event, so that consumers will know when it is safe to access. But if it's a service, its methods are probably already async, right?
As an illustration, let's call the wrapper class MyServiceWrapper. It will load the settings when it is first constructed, and pass through all asynchronous methods in IMyService (for example, SomeMethodAsync as below).
public interface IMyService
{
Task SomeMethodAsync(Action<bool> callback);
}
public class MyServiceWrapper : IMyService
{
private IMyService _impl = null;
private IMyService _remote, _local;
private bool _loaded = false;
private object _sync = new object();
public Task SomeMethodAsync(Action<bool> callback)
{
// first make sure the settings have been loaded
await LoadSettings();
_impl.SomeMethodAsync(callback);
}
public MyServiceWrapper(MyRemoteService remoteService, MyLocalService localService)
{
_remote = remoteService;
_local = localService;
LoadSettings();
}
private async Task<bool> LoadSettings()
{
if (_loaded)
return true;
// lock to prevent multiple threads from loading the settings
lock (_sync)
{
if (_loaded)
return true;
if(await SettingsManager.LoadSettings().EnableRemote)
_impl = _remote;
else
_impl = _local;
}
return true;
}
}
Now you can have your DI container register:
MyRemoteService -> MyRemoteService
MyLocalService -> MyLocalService
IMyService -> MyServiceWrapper
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.