Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.12 KB | None | 0 0
  1. 10.2. Async Construction: Factories Problem You are coding a type that requires some asynchronous work to be done in its constructor. Solution Constructors cannot be async, nor can they use the await keyword. It would certainly be useful to await in a constructor, but this would change the C# language considerably. One possibility is to have a constructor paired with an async initialization method, so the type could be used like this:
  2. var instance = new MyAsyncClass(); await instance.InitializeAsync(); However, there are disadvantages to this approach. It can be easy to forget to call the InitializeAsync method, and the instance is not usable immediately after it was constructed. A better solution is to make the type its own factory. The following type illustrates the asynchronous factory method pattern:
  3. class MyAsyncClass { private MyAsyncClass() { }
  4. private async Task<MyAsyncClass> InitializeAsync()
  5. 10.2. Async Construction: Factories | 137
  6. { await Task.Delay(TimeSpan.FromSeconds(1)); return this; }
  7. public static Task<MyAsyncClass> CreateAsync() { var result = new MyAsyncClass(); return result.InitializeAsync(); } } The constructor and InitializeAsync method are private so that other code cannot possibly misuse them; the only way to create an instance is via the static CreateAsync factory method, and calling code cannot access the instance until after the initialization is complete. Other code can create an instance like this:
  8. var instance = await MyAsyncClass.CreateAsync(); Discussion The primary advantage of this pattern is that there is no way that other code can get an uninitialized instance of MyAsyncClass. That’s why I prefer this pattern over other approaches whenever I can use it. Unfortunately, this approach does not work in some scenarios—in particular, when your code is using a Dependency Injection provider. As of this writing (2014), no major Dependency Injection or Inversion of Control library works with async code. There are a couple of alternatives that you can consider in this case. If the instance you’re creating is actually a shared resource, then you can use the asynchronous lazy type discussed in Recipe 13.1. Otherwise, you can use the asynchronous initialization pattern discussed in Recipe 10.3. Here’s an example of what not to do:
  9. class MyAsyncClass { public MyAsyncClass() { InitializeAsync(); }
  10. // BAD CODE!! private async void InitializeAsync() { await Task.Delay(TimeSpan.FromSeconds(1)); } }
  11. 138 | Chapter 10: Functional-Friendly OOP
  12. At first glance, this seems like a reasonable approach: you get a regular constructor that kicks off an asynchronous operation; however, there are several drawbacks that are due to the use of async void. The first problem is that when the constructor completes, the instance is still being asynchronously initialized, and there isn’t an obvious way to determine when the asynchronous initialization has completed. The second problem is with error handling: any exceptions raised from InitializeAsync can’t be caught by any catch clauses surrounding the object construction.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement