我想通过使用 autofac 正确注入一个使用 api 的 autorest 客户端依赖项(用户在登录后将有自己的令牌使用,但他们可以在登录前使用 api,因为某些方法不需要令牌)。我知道这不是直接的 autorest 问题,它更多的是关于 autofac 但我想给出确切的例子,所以我可以获得更好的建议(也许我做错了,这是一个概念问题)。我查找了一些示例,我发现了一些示例,但在所有示例中,它们只是为一个用户实现,他们没有使用 tokenprovider,他们只是传递了一个预先知道的令牌(这不是用户的令牌,而是用于应用程序)。
我尝试的是使用包装参数(已经注册的多个依赖项将彼此作为构造函数参数)注册 autorest 客户端到容器中。
这就是我注册服务的方式:
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
var sp = ServicePointManager.FindServicePoint(new Uri(ConfigurationManager.AppSettings["WebApiBaseUrl"]));
sp.ConnectionLeaseTimeout = 60 * 1000; // 1 minute
builder.Register(c => new HttpContextWrapper(HttpContext.Current))
.As<HttpContextBase>()
.InstancePerRequest();
builder.RegisterType<TokenProvider>().As<ITokenProvider>().InstancePerLifetimeScope();
builder.RegisterType<TokenCredentials>().Keyed<ServiceClientCredentials>("credentials").InstancePerLifetimeScope();
builder.RegisterType<WebApiClient>()
.As<IWebApiClient>()
.WithParameter("baseUri", new Uri(ConfigurationManager.AppSettings["WebApiBaseUrl"])
).WithParameter("credentials",
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ServiceClientCredentials),
(pi, ctx) => ctx.ResolveKeyed<ServiceClientCredentials>(pi.Name))
).SingleInstance();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
和我的服务:
public partial class WebApiClient : ServiceClient<WebApiClient>, IWebApiClient
{
public WebApiClient(System.Uri baseUri, ServiceClientCredentials credentials = null, params DelegatingHandler[] handlers) : this(handlers)
{
if (baseUri == null)
{
throw new System.ArgumentNullException("baseUri");
}
BaseUri = baseUri;
if (credentials != null)
{
Credentials = credentials;
Credentials.InitializeServiceClient(this);
}
}
}
public class TokenProvider : ITokenProvider
{
private readonly HttpContextBase _context;
public TokenProvider(HttpContextBase context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
{
// this should be async i know(another topic to ask in mvc 5)
var token =_context.Session["ServiceToken"]?.ToString();
if (string.IsNullOrWhiteSpace(token))
{
throw new InvalidOperationException("Could not get an access token from HttpContext.");
}
return new AuthenticationHeaderValue("Bearer", token);
}
}
public class TokenCredentials : ServiceClientCredentials
{
//I want to use this constructor
public TokenCredentials(ITokenProvider tokenProvider);
}
这是我得到的例外
内部异常无法将类型的对象
Autofac.Core.ResolvedParameter
转换为类型Microsoft.Rest.ServiceClientCredentials
。