I'm attempting to register all open generic components I tag with a custom attribute. The query finds the class correctly but the interface is not registered properly. I'm able to register and resolve the component fine using RegisterGeneric
**Working: **
/// <inheritdoc />
[GenericTransient]
public sealed class RetryPolicyService<TResult> : IRetryPolicyService<TResult>
{...
}
builder.RegisterGeneric(typeof(RetryPolicyService<>))
.As(typeof(IRetryPolicyService<>))
.InstancePerDependency();
Not Working:
builder.RegisterAssemblyOpenGenericTypes(Assembly.GetExecutingAssembly())
.Where(t =>
t.GetCustomAttribute<GenericTransientAttribute>() != null)
.As(t => t.GetInterfaces()[0]);
Not Working:
builder.RegisterAssemblyOpenGenericTypes(Assembly.GetExecutingAssembly())
.Where(t =>
t.GetCustomAttribute<GenericTransientAttribute>() != null)
.AsImplementedInterfaces();
The expectation is to be able to inject IRetryPolicyService into objects. Again its working as expected when I register the type specifically.
private readonly IHttpClientService _httpClient;
private readonly IRetryPolicyService<HttpResponseMessage> _retryPolicy;
public ServiceController(
IHttpClientService httpClient,
IRetryPolicyService<HttpResponseMessage> retryPolicy)
{
_httpClient = httpClient;
_retryPolicy = retryPolicy;
_retryPolicy.CreatePolicy(5, times => TimeSpan.FromMilliseconds(times * 1000));
}
The following simplified example works fine. If you uncomment GenericTransient
attribute on the second service then controller will get its instance (last registration wins). And the retryPolicies
variable will get 2 instances.
The first variant (with GetInterfaces()
) also worked after adding .GetGenericTypeDefinition()
.
using Autofac;
using System.Reflection;
namespace Console.Core6
{
internal class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyOpenGenericTypes(Assembly.GetExecutingAssembly())
.Where(t => t.GetCustomAttribute<GenericTransientAttribute>() != null)
.AsImplementedInterfaces();
builder.RegisterAssemblyOpenGenericTypes(Assembly.GetExecutingAssembly())
.Where(t => t.GetCustomAttribute<GenericTransientAttribute>() != null)
.As(t => t.GetInterfaces()[0].GetGenericTypeDefinition());
builder.RegisterType<ServiceController>().InstancePerDependency();
var container = builder.Build();
var controller = container.Resolve<ServiceController>();
var retryPolicies = container.Resolve<IEnumerable<IRetryPolicyService<HttpResponseMessage>>>();
}
}
internal class GenericTransientAttribute : Attribute
{ }
public interface IRetryPolicyService<TResult>
{ }
[GenericTransient]
public sealed class RetryPolicyService<TResult> : IRetryPolicyService<TResult>
{}
//[GenericTransient]
public sealed class RetryPolicyService2<TResult> : IRetryPolicyService<TResult>
{}
public class ServiceController
{
private readonly IRetryPolicyService<HttpResponseMessage> _retryPolicy;
public ServiceController(IRetryPolicyService<HttpResponseMessage> retryPolicy)
{
_retryPolicy = retryPolicy;
}
}
}