类型的构造函数中含有异步操作,为了完全初始化对象实例成功,又不能使用异步工厂模式,因为这个实例是反射动态创建的(控件库依赖注入/反转,数据绑定,Activator.CreateInstance等)。此时可采用异步初始化模式创建实例,多应用于服务端。
static void Main(string[] args)
{
PrintThreadId("Main begin");
Task.Run(() =>
{
PrintThreadId("Thread begin");
DemoTask2().ConfigureAwait(false);
PrintThreadId("Thread END");
});
PrintThreadId("Main END");
Console.ReadKey();
}
/// <summary>
/// 异步初始化场景
/// </summary>
/// <returns></returns>
private static async Task DemoTask2()
{
PrintThreadId("DemoTask2 begin");
if (_fundamental == null)
{
_fundamental = UltimateDIFactory.Create<MyFundamentalType>();
var instanceAsyncInit = _fundamental as IAsyncInitialization;
if (instanceAsyncInit != null)
{
await instanceAsyncInit.Initialization;
}
}
_fundamental.Test();
PrintThreadId("DemoTask2 END");
}
static IMyFundamentalType _fundamental;
/// <summary>
/// 当前线程信息
/// </summary>
/// <param name="msg"></param>
static void PrintThreadId(string msg)
{
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{Thread.CurrentThread.ManagedThreadId}]: {msg}");
}
/// <summary>
/// 类型定义
/// </summary>
class MyFundamentalType : IMyFundamentalType, IAsyncInitialization
{
public Task Initialization { get; private set; }
private readonly IMyFundamentalType _otherType;
private readonly IMyFundamentalType _another;
private readonly IMyFundamentalType _another2;
public MyFundamentalType(IMyFundamentalType otherType, IMyFundamentalType another, IMyFundamentalType another2)
{
_otherType = otherType;
_another = another;
_another2 = another2;
Initialization = InitializeAsync();
}
private async Task InitializeAsync()
{
PrintThreadId("MyFundamentalType InitializeAsync begin");
// 异步等待3个实例初始化
await AsyncInitialization.WhenAllInitializedAsync(_otherType, _another, _another2);
// 自己的异步初始化过程
await Task.Delay(TimeSpan.FromSeconds(2));
PrintThreadId("MyFundamentalType InitializeAsync END");
}
/// <summary>
/// 类型方法
/// </summary>
public void Test()
{
Console.WriteLine("MyFundamentalType.Test Method");
}
}
/// <summary>
/// 需要DI的类型1
/// </summary>
public class MyFundamentalTest : IMyFundamentalType, IAsyncInitialization
{
public Task Initialization { get; private set; }
public MyFundamentalTest()
{
Initialization = InitializeAsync();
}
private async Task InitializeAsync()
{
PrintThreadId("IMyFundamentalType Test1 InitializeAsync begin");
// 自己的异步初始化过程
await Task.Delay(TimeSpan.FromSeconds(1));
PrintThreadId("IMyFundamentalType Test1 InitializeAsync END");
}
public void Test() { }
}
/// <summary>
/// 需要DI的类型2
/// </summary>
public class MyFundamentalTest2 : IMyFundamentalType, IAsyncInitialization
{
public Task Initialization { get; private set; }
public MyFundamentalTest2()
{
Initialization = InitializeAsync();
}
private async Task InitializeAsync()
{
PrintThreadId("IMyFundamentalType Test2 InitializeAsync begin");
// 自己的异步初始化过程
await Task.Delay(TimeSpan.FromSeconds(2));
PrintThreadId("IMyFundamentalType Test2 InitializeAsync END");
}
public void Test() { }
}
/// <summary>
/// 需要DI的类型3
/// </summary>
public class MyFundamentalTest3 : IMyFundamentalType, IAsyncInitialization
{
public Task Initialization { get; private set; }
public MyFundamentalTest3()
{
Initialization = InitializeAsync();
}
private async Task InitializeAsync()
{
PrintThreadId("IMyFundamentalType Test3 InitializeAsync begin");
// 自己的异步初始化过程
await Task.Delay(TimeSpan.FromSeconds(3));
PrintThreadId("IMyFundamentalType Test3 InitializeAsync END");
}
public void Test() { }
}
/// <summary>
/// 为那些需要异步初始化器的对象定义一个标记接口
/// </summary>
public interface IAsyncInitialization
{
/// <summary>
/// 初始化器的结果
/// </summary>
Task Initialization { get; }
}
/// <summary>
/// 同类型接口
/// </summary>
interface IMyFundamentalType
{
void Test();
}
/// <summary>
/// 异步初始化器辅助类
/// </summary>
public static class AsyncInitialization
{
/// <summary>
/// 含有异步初始化器的对象全部完成
/// </summary>
/// <param name="instances"></param>
/// <returns></returns>
public static Task WhenAllInitializedAsync(params object[] instances)
{
return Task.WhenAll(instances.OfType<IAsyncInitialization>().Select(x => x.Initialization));
}
}
/// <summary>
/// DI工厂
/// </summary>
public static class UltimateDIFactory
{
public static T Create<T>()
{
var test = new Program.MyFundamentalTest();
var test2 = new Program.MyFundamentalTest2();
var test3 = new Program.MyFundamentalTest3();
return (T)Activator.CreateInstance(typeof(T), test, test2, test3);
}
}