Inject a dependency in a SeriLog enricher with autofac - autofac

I want to create a Serilog Enricher injecting some data from a dependency. How can autofac inject my dependency into an enricher?
This is my container setup:
builder.Register((c, p) =>
{
return new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.With<MyEnricherWhichCanAddMoreDataFromADependency>()
// ...
.CreateLogger();
}).As<ILogger>();
While the enricher would look something like
public class MyEnricherWhichCanAddMoreDataFromADependency : ILogEventEnricher
{
public MyEnricherWhichCanAddMoreDataFromADependency(IDependency d)
{ ... do stuff with the dependency ... }
}
Constructor injection does not seem to work. Or am I doing something wrong?

When you enrich With<T> all it's doing, literally, is calling new T().
If you want to pass the enricher through DI you need to do that yourself.
builder.Register((c, p) =>
{
var e = c.Resolve<MyEnricherWhichCanAddMoreDataFromADependency>();
return new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.With(e)
// ...
.CreateLogger();
}).As<ILogger>();

Related

autofac webapi owin integration problems with middleware exection order not correct

I'm confused with Autofac Examples : WebApiExample.OwinSelfHost, the startup class is following:
public class Startup
{
public void Configuration(IAppBuilder app)
{
// In OWIN you create your own HttpConfiguration rather than
// re-using the GlobalConfiguration.
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
var builder = new ContainerBuilder();
// Register Web API controller in executing assembly.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL - Register the filter provider if you have custom filters that need DI.
// Also hook the filters up to controllers.
builder.RegisterWebApiFilterProvider(config);
builder.RegisterType<CustomActionFilter>()
.AsWebApiActionFilterFor<TestController>()
.InstancePerRequest();
// Register a logger service to be used by the controller and middleware.
builder.Register(c => new Logger()).As<ILogger>().InstancePerRequest();
// Autofac will add middleware to IAppBuilder in the order registered.
// The middleware will execute in the order added to IAppBuilder.
builder.RegisterType<FirstMiddleware>().InstancePerRequest();
builder.RegisterType<SecondMiddleware>().InstancePerRequest();
// Create and assign a dependency resolver for Web API to use.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// The Autofac middleware should be the first middleware added to the IAppBuilder.
// If you "UseAutofacMiddleware" then all of the middleware in the container
// will be injected into the pipeline right after the Autofac lifetime scope
// is created/injected.
//
// Alternatively, you can control when container-based
// middleware is used by using "UseAutofacLifetimeScopeInjector" along with
// "UseMiddlewareFromContainer". As long as the lifetime scope injector
// comes first, everything is good.
app.UseAutofacMiddleware(container);
// Again, the alternative to "UseAutofacMiddleware" is something like this:
// app.UseAutofacLifetimeScopeInjector(container);
// app.UseMiddlewareFromContainer<FirstMiddleware>();
// app.UseMiddlewareFromContainer<SecondMiddleware>();
// Make sure the Autofac lifetime scope is passed to Web API.
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
The FirstMiddleware and SecondMiddleware code was as following:
public class FirstMiddleware : OwinMiddleware
{
private readonly ILogger _logger;
public FirstMiddleware(OwinMiddleware next, ILogger logger) : base(next)
{
this._logger = logger;
}
public override async Task Invoke(IOwinContext context)
{
this._logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name);
await Next.Invoke(context);
}
}
public class SecondMiddleware : OwinMiddleware
{
private readonly ILogger _logger;
public SecondMiddleware(OwinMiddleware next, ILogger logger) : base(next)
{
this._logger = logger;
}
public override async Task Invoke(IOwinContext context)
{
this._logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name);
await Next.Invoke(context);
}
}
According to the comments, the middleware registration order matters. FirstMiddleware first, then SecondMiddleware. but the output was second middleware was invoked first.
the program logs output here
What's wrong with the order?
This is the autofac official example.WebApiExample.OwinSelfHost
Looks like you've found a bug! I've filed an issue about it on your behalf. You can read more technical details about it there, but the short version is that over the years we've changed some Autofac internals to support .NET Core and this looks like something we've missed.
The workaround until this is fixed will be to register the middleware in reverse order, which isn't awesome because once the fix is applied you'll have to reverse them back. :(

How to resolve public class with internal constructor on AutoFac

I have this class to be instantiated in a unittest:
public class Customer
{
internal Customer(Guid id) {
// initialize property
}
}
If I instantiate the test class from another (unittests) assembly with a new Customer() works because I added [assembly: InternalsVisibleTo("MyProject.Tests")]
var sut = new Customer(Guid.NewGuid()); // works
But when i setup an autofac container in the other (unittest) assembly
var builder = new ContainerBuilder();
builder.RegisterType<Customer>().AsSelf();
var container = builder.Build();
I can't resolve with autofac.
var theParam = new NamedParameter("id", Guid.NewGuid());
_sut = container.Resolve<Customer>(theParam); // throws exception
My best guess was that the internal constructor was not available. But adding [assembly: InternalsVisibleTo("Autofac")] next to the other doesn't help.
The exception thown by Autofac is
Autofac.Core.DependencyResolutionException:
An error occurred during the activation of a particular registration. See the inner exception for details.
Registration: Activator = Customer (ReflectionActivator),
Services = [MyProject.Customer],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = OwnedByLifetimeScope
---> No accessible constructors were found for the type 'MyProject.Customer'.
Can Autofac not handle internal constructors?
Autofac can't locate non-public constructors because it uses the DefaultConstructorFinder class which searches only for public constructors by default.
You have to create your custom implementation of the IConstructorFinder interface like this:
public class AllConstructorFinder : IConstructorFinder
{
private static readonly ConcurrentDictionary<Type, ConstructorInfo[]> Cache =
new ConcurrentDictionary<Type, ConstructorInfo[]>();
public ConstructorInfo[] FindConstructors(Type targetType)
{
var result = Cache.GetOrAdd(targetType,
t => t.GetTypeInfo().DeclaredConstructors.Where(c => !c.IsStatic).ToArray());
return result.Length > 0 ? result : throw new NoConstructorsFoundException(targetType);
}
}
Then you have to use the FindConstructorsWith extension method on type registration:
builder.RegisterType<Customer>()
.FindConstructorsWith(new AllConstructorFinder())
.AsSelf();
The InternalsVisibleToAttribute can't help in this case because it affects only the compile time.
if you want to register assembly types with at least only has one public constructor then you can use Autofac Where extension method like this.
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.GetConstructors().Length > 0) //only public constructors
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
Note: PublicOnly extension method registers only public types.

How can I register a (boundless) type hierarchy using Autofac?

I've got a Factory interface (along with concrete implementations):
// foo.dll
interface IFooProvider
{
T GetFoo<T>()
where T : BaseFoo;
}
My BaseFoo is not abstract, but only its subclasses are actually useful:
// shared.dll
class BaseFoo
{ ... }
I've also got a (potentially unbounded) number of subclasses of BaseFoo across many assemblies:
// foo.dll
class AFoo : BaseFoo
{ ... }
// foo2.dll
class BFoo : BaseFoo
{ ... }
... and many more ...
Naively, I had been registering the Foo-derived classes in an unsurprising way:
// foo.dll
class ConcreteFooRegistration : Module
{
protected override void Load(ContainerBuilder builder)
{
// a concrete FooProvider is registered elsewhere
builder.Register(c => c.Resolve<IFooProvider>().GetFoo<AFoo>());
builder.Register(c => c.Resolve<IFooProvider>().GetFoo<BFoo>());
...
}
}
But this implies that:
the assembly containing ConcreteFooRegistration (e.g. foo.dll) also contains some/all of AFoo, BFoo, etc.
the assembly containing ConcreteFooRegistration (e.g. foo.dll) references the assemblies (e.g. foo2.dll) containing some/all of AFoo, BFoo, etc.
IFooProvider be available to any other assembly containing BaseFoo-derived classes and the Module that registers them
For sake of discussion, assume that none of these is possible and/or desirable. That is, I'm looking for solutions other than "move IFooProvider into shared.dll".
Since AFoo and BFoo are the real dependencies that other types are interested in, and IFooProvider is (from that perspective) just an instantiation detail, I got inspired by the Autofac+Serilog integration that Nicholas came up with. I've used a similar approach elsewhere, so I wrote up an AttachToComponentRegistration() implementation:
// foo.dll
class ConcreteFooRegistration : Module
{
// NOTICE: there's no Load() method
protected override void AttachToComponentRegistration(...)
{
...
registration.Preparing += (sender, e) =>
{
var pFoo = new ResolvedParameter(
(p, i) => p.ParameterType.IsAssignableTo<BaseFoo>(),
(p, i) => i.Resolve<IFooProvider>().GetFoo<FooWeNeed>()
);
e.Parameters = new [] { pFoo }.Concat(e.Parameters);
};
}
}
This was successful, in that I was able to remove all the individual BaseFoo-derived registrations from ConcreteFooRegistration and still successfully resolve arbitrary BaseFoo-derived dependencies with constructor injection:
// other.dll:
class WorkerRegisteration : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Worker>();
// NOTICE: FooYouDidntKnowAbout is NOT explicitly registered
}
}
class Worker
{
public Worker(FooYouDidntKnowAbout foo)
{ ... }
...
}
BUT: now I can't arbitrarily resolve AFoo outside of constructor injection:
builder.Register(c =>
{
// here's one use for a BaseFoo outside constructor injection
var foo = c.Resolve<AFoo>();
if (foo.PropValue1)
return new OtherClass(foo.PropValue2);
else
return new YetAnother(foo.PropValue3);
}
...
builder.Register(c =>
{
// here's another
var foo = c.Resolve<AFoo>();
return c.Resolve(foo.TypePropValue);
});
Assuming that publishing IFooProvider as a public export of foo.dll or moving it to shared.dll is undesirable/impossible, thus eliminating the naive-but-unsurprising implementation above, (how) can I set up my registrations to be able to resolve arbitrary subclasses of BaseFoo from anywhere?
Thanks!
I think what you're looking for is a registration source. A registration source is a dynamic "registration provider" you can use to feed Autofac registrations as needed.
As of this writing, the doc on registration sources is pretty thin (I just haven't gotten a chance to write it) but there's a blog article with some details about it.
Registration sources are how Autofac supports things like IEnumerable<T> or Lazy<T> - we don't require you actually register every collection, instead we dynamically feed the registrations into the container using sources.
Anyway, let me write you up a sample here and maybe I can use it later to massage it into the docs, eh? :)
First, let's define a very simple factory and implementation. I'm going to use "Service" instead of "Foo" here because my brain stumbles after it sees "foo" too many times. That's a "me" thing. But I digress.
public interface IServiceProvider
{
T GetService<T>() where T : BaseService;
}
public class ServiceProvider : IServiceProvider
{
public T GetService<T>() where T : BaseService
{
return (T)Activator.CreateInstance(typeof(T));
}
}
OK, now let's make the service types. Obviously for this sample all the types are sort of in one assembly, but when your code references the type and the JIT brings it in from some other assembly, it'll work just the same. Don't worry about cross-assembly stuff for this.
public abstract class BaseService { }
public class ServiceA : BaseService { }
public class ServiceB : BaseService { }
Finally, a couple of classes that consume the services, just so we can see it working.
public class ConsumerA
{
public ConsumerA(ServiceA service)
{
Console.WriteLine("ConsumerA: {0}", service.GetType());
}
}
public class ConsumerB
{
public ConsumerB(ServiceB service)
{
Console.WriteLine("ConsumerB: {0}", service.GetType());
}
}
Good.
Here's the important bit, now: the registration source. The registration source is where you will:
Determine if the resolve operation is asking for a BaseService type or not. If it's not, then you can't handle it so you'll bail.
Build up the dynamic registration for the specific type of BaseService derivative being requested, which will include the lambda that invokes the provider/factory to get the instance.
Return the dynamic registration to the resolve operation so it can do the work.
It looks like this:
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;
public class ServiceRegistrationSource : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if(swt == null || !typeof(BaseService).IsAssignableFrom(swt.ServiceType))
{
// It's not a request for the base service type, so skip it.
return Enumerable.Empty<IComponentRegistration>();
}
// This is where the magic happens!
var registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (c, p) =>
{
// The factory method is generic, but we're working
// at a reflection level, so there's a bit of crazy
// to deal with.
var provider = c.Resolve<IServiceProvider>();
var method = provider.GetType().GetMethod("GetService").MakeGenericMethod(swt.ServiceType);
return method.Invoke(provider, null);
}),
new CurrentScopeLifetime(),
InstanceSharing.None,
InstanceOwnership.OwnedByLifetimeScope,
new [] { service },
new Dictionary<string, object>());
return new IComponentRegistration[] { registration };
}
public bool IsAdapterForIndividualComponents { get{ return false; } }
}
It looks complex, but it's not too bad.
The last step is to get the factory registered as well as the registration source. For my sample, I put those in an Autofac module so they're both registered together - it doesn't make sense to have one without the other.
public class ServiceProviderModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ServiceProvider>().As<IServiceProvider>();
builder.RegisterSource(new ServiceRegistrationSource());
}
}
Finally, let's see it in action. If I throw this code into a console app...
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<ConsumerA>();
builder.RegisterType<ConsumerB>();
builder.RegisterModule<ServiceProviderModule>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var a = scope.Resolve<ConsumerA>();
var b = scope.Resolve<ConsumerB>();
}
}
What you end up with on the console is:
ConsumerA: ServiceA
ConsumerB: ServiceB
Note I had to register my consuming classes but I didn't explicitly register any of the BaseService-derived classes - that was all done by the registration source.
If you want to see more registration source samples, check out the Autofac source, particularly under the Autofac.Features namespace. There you'll find things like the CollectionRegistrationSource, which is responsible for handling IEnumerable<T> support.

Can Autofac compose existing objects with Mef dependencies?

I am integrating a mef-based ServiceLocator with Autofac. The current locator is able to compose an existing object by setting up a CompositionBatch and then injecting dependecies on the object. A simple repro:
public void MefCompositionContainer_CanComposeExistingObjects()
{
//1. Initialize Mef
var composablePartCatalogs = new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
//A lot more here..
};
var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);
var container = new CompositionContainer(aggregateCatalog, true);
//2. Mef is able to compose existing object
var objectWithPropertyImport = new ClassWithPropertyImport();
Compose(container, objectWithPropertyImport);
objectWithPropertyImport.ImportOfMefExport.Should().NotBeNull();
}
static T Compose<T>(CompositionContainer container, T value)
{
var batch = new CompositionBatch();
batch.AddPart(value);
container.Compose(batch);
return value;
}
The following classes are required:
[Export]
public class MefExport { }
//Note that this class does not have the [Export] attribute
public class ClassWithPropertyImport
{
[Import]
public MefExport ImportOfMefExport { get; set; }
}
Is it possible to accomplish the same with Autofac? If so - what should be added / changed here to compose objectWithPropertyImport?
public void Autofac_CanComposeExistingObjects()
{
//1. Initialize Mef
var composablePartCatalogs = new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
//A lot more here..
};
var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);
//2. Initialize Autofac and setup mef-integration
var builder = new ContainerBuilder();
builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>());
builder.RegisterComposablePartCatalog(aggregateCatalog);
var ioc = builder.Build();
var objectWithPropertyImport = new ClassWithPropertyImport();
// Now what?
// Updated according to solution from Travis Illig.
// The following code works for me:
ioc.InjectProperties(objectWithPropertyImport);
objectWithPropertyImport.ImportOfMefExport.Should().NotBeNull();
}
If all you need to do is inject the properties of a new object using Autofac, then use the InjectProperties method on the lifetime scope / container.
using Autofac;
public class ClassWithPropertyImport
{
public MyExport ImportedProperty { get; set; }
}
public class MyExport { }
var builder = new ContainerBuilder();
builder.RegisterType<MyExport>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var c = new ClassWithPropertyImport();
scope.InjectProperties(c);
c.ImportedProperty.Should().NotBeNull();
}
As long as the types you're injecting are registered with Autofac, it should work fine. You don't need the type of the thing you're injecting onto registered. (Note the ClassWithPropertyImport is not registered with Autofac but the MyExport class is.)
Keep in mind it does mean Autofac needs to resolve the MyExport type - so if it has dependencies, those do need to be registered with Autofac as well.

Register delegate-func by convention

On the ContainerBuilder i can do the following:
builder.Register<ScenariosConfig>(c =>
(ScenariosConfig)c.Resolve<ConfigFactory>()
.Create(typeof(ScenariosConfig)))
.SingleInstance();
With assembly scanning i can do the following:
builder.RegisterAssemblyTypes(assemblies)
.Where(HasSingletonAttribute)
.As(t => GetNameMatchingInterfaces(t))
.SingleInstance();
Now the question: Is there any way to achieve the following: ?
builder.RegisterAssemblyTypes(assemblies)
.Where(... some condition)
.CreateByDelegate((container, type)
=> c.Resolve<ConfigFactory>().Create(type))
.SingleInstance();
I've already found out about IRegistrationSource with which i can achieve something similar. However, I'm a bit skeptic about the performance impact of creating ton's of IRegistrationSource's for each of my conventions which require a delegate for creation...
And also there's the fact that IRegistrationSource can't be used whenever you need to resolve all instances of IFoo which should be bound by such a "convention".
In the end we did choose to use an IRegistrationSource. The only alternative i've "found" would have been to detect all types per reflection (not using autofac API...) and then generating a delegate for each and registering this with autofac. Would not really result in code that easily understandable...
So for completeness sake' here's the IRegistrationSource implementation:
public class ConfigConventionRegistrationSource : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var s = service as IServiceWithType;
if (s != null
&& s.ServiceType.IsClass
&& s.ServiceType.Name.EndsWith("Config")
&& !s.ServiceType.GetInterfaces().Any())
{
yield return RegistrationBuilder
.ForDelegate((componentContext, parameters) =>
CreateConfigByFactory(componentContext, s.ServiceType))
.As(s.ServiceType)
.SingleInstance()
.CreateRegistration();
}
}
private static object CreateConfigByFactory(
IComponentContext componentContext,
Type configType)
{
IConfig configFactory = componentContext.Resolve<IConfig>();
MethodInfo method = Reflector<IConfig>
.GetMethod(x => x.Load<object>())
.GetGenericMethodDefinition()
.MakeGenericMethod(configType);
try
{
return method.Invoke(configFactory, new object[0]);
}
catch (TargetInvocationException tex)
{
ExceptionDispatchInfo
.Capture(tex.InnerException)
.Throw();
throw; // will not be reached as thrown above ;-)
}
}
public bool IsAdapterForIndividualComponents
{
get { return false; }
}
}