Я хочу правильно внедрить клиентскую зависимость autorest, которая использует api (у которых пользователи будут использовать свой собственный токен после входа в систему, но они могут использовать api до входа в систему для некоторых методов, токен не требуется) с помощью 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
.