Satisfy Imports in custom ExportProvider - mef

I'd like to know how I can have Imports in my custom ExportProvider. Here's an example of what I'm trying to do:
public class MyExportProvider : ExportProvider
{
private List<Export> _exports;
[Import()]
private IConfig _config;
public MyExportProvider()
base()
{
_exports = new List<Export>();
}
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition,
AtomicComposition composition)
{
if (!_exports.Any())
Initialize();
return _exports.Where(x => definition.IsConstraintSatisfiedBy(s.Definition);
}
private void Initialize()
{
var contractName = typeof(MyObject).FullName;
var exportDefinition = new ExportDefinition(contractName, null);
var export = new Export(exportDefinition, () => new MyObject(_config));
_exports.Add(export);
}
}
I am adding the provider when I create the CompositionContainer.
Unfortunately, the import is never satisfied. I can see this by setting AllowDefaults = true so my provider is created, but _config is always null.
How can I configure the container and/or provider so the Import will be satisfied?

When you are adding your export provider you are still creating your composition container. Thus I don't see how you can use the not yet created composition container to import parts of your custom export provider.
What I would do is first create a temporary CompositionContainer that will be used to create MyExportProvider.
Afterwards use the MyExportProvider to create your second final CompositionContainer that will be used by the rest of the application.
EDIT:
// this is your real container, only shown here for reference
CompositionContainer container;
public void BootstrapContainerMethod()
{
// Replace this part with the catalogs required to create your export provider.
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("./bin", "*.dll"));
// Your temporary container, declared here in local scope
// will be disposed because of using
using (var bootstrapContainer = new CompositionContainer(catalog))
{
var myExportProvider = bootstrapContainer.GetExportedValue<IMyExportProvider>();
// create your real container and optionnally add catalogs (not shown here)
container = new CompositionContainer(myExportProvider);
}
}
You might also consider the problem from another angle. Do you really need to have imports in your custom ExportProvider? I do not know your requirements, but maybe you can make do without having imports.

As an alternative to the dual CompositionContainer solution, you could wire this up in a single export provider, and have it compose itself using the same container. As an example, I've defined the following contract and it's export:
public interface ILogger
{
void Log(string message);
}
[Export(typeof(ILogger))]
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
And with my example ExportProvider, I expect to be able to import an instance of it:
public class TestExportProvider : ExportProvider
{
private readonly object _lock = new object();
private bool _initialised;
[Import]
public ILogger Logger { get; set; }
public void SetCompositionService(ICompositionService service)
{
if (service == null) throw new ArgumentNullException("service");
lock (_lock)
{
if (!_initialised)
{
InitialiseProvider(service);
}
}
}
private void InitialiseProvider(ICompositionService service)
{
service.SatisfyImportsOnce(this);
_initialised = true;
}
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
{
if (_initialised)
{
Logger.Log("Getting available exports for '" + definition.ContractName + "'");
// Do work here.);
return Enumerable.Empty<Export>();
}
return Enumerable.Empty<Export>();
}
}
I provide an instance of an ICompositionService, which CompositionContainer implements, and I perform a first-time initialisation when I call SetCompositionService. It checks to see if it has already been initialised, and if not, goes ahead and calls the SatisfyImportsOnce method on itself.
We would wire this up, something like this:
// Build our catalog.
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
// Create our provider.
var provider = new TestExportProvider();
// Create our container.
var container = new CompositionContainer(catalog, provider);
// Register the composition service to satisfy it's own imports.
provider.SetCompositionService(container);
Obviously you wouldn't be able to use any imports and your ExportProvider will explicitly create for you, but for everything else, it should work.

Related

Concrete type instance registration in Autofac fails to resolve in a nested scope when using AnyConcreteTypeNotAlreadyRegisteredSource source

I have an Autofac container that uses "AnyConcreteTypeNotAlreadyRegisteredSource" to allow resolution of any concrete type without explicit need to register it. If I register a singleton instance of a concrete type using the RegisterInstance method, there are no issues with the resolution. However, if I create a child lifetime scope and do the same concrete type singleton instance registration, the child lifetime scope is not able to resolve the type anymore. It throws the following exception:
Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'AutofacTests.IssueTests+Manager'.'
Why is it even trying to instantiate the object when I have a singleton instance of that type registered already? It seems like this problem only comes when I try to resolve a concrete type instead of an interface.
Here is the test code that demonstrates the problem (The test method name and comments show what works and what does not):
using Autofac;
using Autofac.Features.ResolveAnything;
namespace AutofacTests
{
[TestClass]
public class IssueTests
{
private interface IPerson
{
}
private class Employee : IPerson
{
public Employee()
{
}
}
private class Manager : Employee
{
internal Manager(IPerson worker)
{
string s = "";
}
}
[TestMethod]
public void Resolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void ResolutionWithAnyTypeSource_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration does not impact the concrete type resolution when no child lifetime scope is involved.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void NestedResolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
var person = childContainer.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
}
[TestMethod]
public void NestedResolutionWithAnyTypeSource_ThatFails()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration causes the resolution of a concrete type to fail in a child lifetime scope.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
// Works
var person = childContainer.Resolve<IPerson>();
Assert.IsNotNull(person, "Person could not be resolved!");
// *** Fails ***
var emp = childContainer.Resolve<Manager>();
Assert.IsNotNull(emp, "Employee could not be resolved!");
}
}
}
}
}
Anyone has any idea what am I doing wrong or how to make this work in the child lifetime scopes?
Thanks.
It appears you're hitting this known issue where AnyConcreteTypeNotAlreadyRegisteredSource (ACTNARS) doesn't properly look at new registrations in child scopes.
At the time of this writing there is not a fix for it, but we'd love a PR to get it fixed. It's been open for a while now.

Testing code in a custom NancyFx Bootstrapper

I have a custom Nancy Bootstrapper which uses StructureMapNancyBootstrapper but the issue is the same regardless of container.
public class CustomNancyBootstrapper : StructureMapNancyBootstrapper
{
protected override void RequestStartup(IContainer container, IPipelines pipelines, NancyContext context)
{
var auth = container.GetInstance<ICustomAuth>();
auth.Authenticate(context);
}
}
I want to write a test to assert that Authenticate is called with the context... something like this...
[Test]
public void RequestStartup_Calls_CustomAuth_Authenticate_WithContext()
{
// set up
var mockAuthentication = new Mock<ICustomAuth>();
var mockContainer = new Mock<IContainer>();
var mockPipelines = new Mock<IPipelines>();
var context = new NancyContext();
mockContainer.Setup(x => x.GetInstance<ICustomAuth>()).Returns(mockAuthentication.Object);
// exercise
_bootstrapper.RequestStartup(_mockContainer.Object, _mockPipelines.Object, context);
// verify
mockAuthentication.Verify(x => x.Authenticate(context), Times.Once);
}
The problem is that I can't call RequestStartup because it's protected as defined in NancyBootstrapperBase.
protected virtual void RequestStartup(TContainer container, IPipelines pipelines, NancyContext context);
Is there a "proper"/"offical" Nancy way to do this without creating another derived class and exposing the methods as that just seems like a hack?
Thanks
I guess you can "fake" the request by using Browser from Nancy.Testing:
var browser = new Browser(new CustomNancyBootstrapper());
var response = browser.Get("/whatever");
There is a good set of articles about testing NancyFx application:
http://www.marcusoft.net/2013/01/NancyTesting1.html
Turns out Nancy offers a IRequetStartup interface so you can take the code out of the custom bootstrapper and do something like this...
public class MyRequestStart : IRequestStartup
{
private readonly ICustomAuth _customAuthentication;
public MyRequestStart(ICustomAuth customAuthentication)
{
if (customAuthentication == null)
{
throw new ArgumentNullException(nameof(customAuthentication));
}
_customAuthentication = customAuthentication;
}
public void Initialize(IPipelines pipelines, NancyContext context)
{
_customAuthentication.Authenticate(context);
}
}
and the test is easy and concise
[Test]
public void When_Initialize_Calls_CustomAuth_Authenticate_WithContext()
{
// set up
var mockAuth = new Mock<ICustomAuth>();
var requestStartup = new MyRequestStart(mockAuth.Object);
var mockPipeline = new Mock<IPipelines>();
var context = new NancyContext();
// exercise
requestStartup.Initialize(mockPipeline.Object, context);
// verify
mockAuth.Verify(x => x.Authenticate(context), Times.Once);
}
https://github.com/NancyFx/Nancy/wiki/The-Application-Before%2C-After-and-OnError-pipelines#implementing-interfaces

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.

EF: How to enclose context object in a using statement?

Let's say I have the following classes Customer.cs, a context OfficeContext.cs, and a repository OfficeRepository.cs. Knowing that the context use a connection object, so it's advised to enclose it in a using statement:
public List<Customer> GetAllCustomersWithOrders()
{
using(var oContext = new OfficeContext())
{
//Code here....
}
}
My question is what if I want to re-use some of the code already in the repository? For instance, what if I want to display all the customers that ordered products but didn't receive them yet, do I need to duplicate the code?
public List<Customer> GetCustomersNotReceiveProducts()
{
using(var oContext = new OfficeContext())
{
//Re-use GetAllCustomersWithOrders() here???...
}
}
But as you can see, each time access a method, I also open instantiate a new context object. Is there any way to deal with that?
What I do is have my repositories implement IDisposable.
Then have two constructors (one default) that instaniates a new context that holds it as a class level variable. And another constructor that takes a context and uses that internally.
The on the dispose of the class the context is disposed (if the current repository instatiated it).
This removes the context out of the method level and moves it to the class level. My functions keep everything in IQueryable so one function can call another function and perform additional refinements before the database it hit.
Exmaple:
public class MemberRepository : IDisposable
{
OfficeContext db;
bool isExternalDb = false;
public MemberRepository()
{
db = new OfficeContext();
isExternalDb = false;
}
public MemberRepository(OfficeContext db)
{
this.db = db;
isExternalDb = true;
}
public IQueryable<Member> GetAllMembers()
{
var members= db.Members
return members;
}
public IQueryable<Member> GetActiveMembers()
{
var members = GetAllMembers();
var activeMembers = members.Where(m => m.isActive == true);
return activeMembers;
}
public void Dispose()
{
if (isExternalDb == false)
{
db.Dispose();
}
}
}
Then where I use the repository, I do a using at that level:
using(var memberRepository = new MemberRepository())
{
var members = memberRepository.GetActiveMembers();
}