有人可以帮我解决一个问题吗?
我有两项服务。
GAuth:
public class GAuth : IGAuth
{
public async Task<UserCredential> AuthorizeAsync(ClientSecrets clientSecrets)
{
using (var cts = new CancellationTokenSource())
{
var localServerCodeReceiver = new LocalServerCodeReceiver();
cts.CancelAfter(TimeSpan.FromMinutes(1));
return await GoogleWebAuthorizationBroker.AuthorizeAsync(
clientSecrets,
_scopes,
User,
cts.Token,
new FileDataStore(string.Empty), localServerCodeReceiver
);
}
}
}
GDrive的:
public class GDrive : IGDrive
{
private readonly DriveService _driveService;
public GDrive(UserCredential userCredential)
{
_driveService = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = userCredential,
ApplicationName = string.Empty
});
}
}
和注册部分:
container.Register<IGAuth, GAuth>(Lifestyle.Singleton);
container.Register<IGDrive, GDrive>(Lifestyle.Singleton);
正如您所见,GAuth
服务在授权后返回UserCredentials
个对象。 UserCredentials
服务需要此GDrive
。
这是一个简化的示例,但一般情况下,我需要在用户按申请表单上的GDrive
按钮后使用正确的UserCredentials
对象初始化Auth
服务。
有没有办法做到这一点?
提前致谢。
答案 0 :(得分:1)
从设计角度来看,注入构造函数应该是simple, fast and reliable。在您的情况下情况并非如此,因为对象图的构建取决于I / O.
相反,您应该将IO推迟到构造函数运行之后。
我能想到你能做的两件事。您可以将IGAuth
注入GDrive并确保在构造函数运行后调用它,或者注入构造函数运行后可以请求的惰性异步UserCredential
。
以下是后者的一个例子:
public class GDrive : IGDrive
{
private readonly Lazy<Task<DriveService>> _driveService;
public GDrive(Lazy<Task<UserCredential>> userCredential)
{
_driveService = new Lazy<Task<DriveService>>(async () =>
new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = await userCredential.Value,
ApplicationName = string.Empty
}));
}
public async Task SomeMethod()
{
var service = await _driveService.Value;
service.DoSomeStuff();
}
}
您可以按如下方式配置此GDrive
:
var auth = new GAuth();
var credentials = new Lazy<Task<UserCredential>>(
() => auth.AuthorizeAsync(new ClientSecrets()));
container.RegisterSingleton<IGDrive>(new GDrive(credentials));
另一种选择是将GAuth
注入GDrive
。这将产生如下内容:
public class GDrive : IGDrive
{
private readonly Lazy<Task<DriveService>> _driveService;
public GDrive(IGAuth auth)
{
_driveService = new Lazy<Task<DriveService>>(async () =>
new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = await auth.AuthorizeAsync(new ClientSecrets()),
ApplicationName = string.Empty
}));
}
public async Task SomeMethod()
{
var service = await _driveService.Value;
service.DoSomeStuff();
}
}
请注意,在这两种情况下都会创建Lazy<Async<T>>
,以确保仅在首次调用Lazy<T>.Value
时触发异步操作。