Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing the same type twice in constructor #348

Closed
alexmg opened this issue Jan 22, 2014 · 7 comments
Closed

Importing the same type twice in constructor #348

alexmg opened this issue Jan 22, 2014 · 7 comments
Labels

Comments

@alexmg
Copy link
Member

alexmg commented Jan 22, 2014

From [email protected] on November 11, 2011 04:54:01

What steps will reproduce the problem? 1.Register a class (A) that inject a MEF exported class (B) twice in constructor.
2.Make sure that the MEF exported class (B) import at least one other class (C) in constructor. It can be Autofac or MEF exported. Doesn't seem to matter.
3.Try resolve class A.

What is the expected output?
The type should be resolved successfully.

What do you see instead?
I get an exception along the lines of:
{"GetExportedValue cannot be called before prerequisite import 'AutofacMef.MefClass..ctor (Parameter="dependency", ContractName="AutofacMef.StandardDependency")' has been set."} What version of Autofac are you using? On what version of .NET/Silverlight? Autofac(.Mef) 2.5.2.830
.NET 4 Please provide any additional information below. I've attached a solution which shows the error.

Attachment: AutofacMef.zip

Original issue: http://code.google.com/p/autofac/issues/detail?id=348

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From [email protected] on January 22, 2012 21:19:48

Thank you for the report and repro, I'll try to take a look at this ASAP.

Status: Accepted

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on September 21, 2012 09:33:45

Labels: Module-Integration-Mef

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on July 15, 2013 09:54:38

Verified this is still an issue in the 3.0 code. Doing the same thing in just Autofac works; it's definitely something in the MEF integration code.

Status: Started
Owner: travis.illig

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on July 15, 2013 10:52:41

The stack trace for the resolution exception:
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\ResolveOperation.cs:line 89 at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Lifetime\LifetimeScope.cs:line 230
at Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Container.cs:line 181 at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\ResolutionExtensions.cs:line 786
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\ResolutionExtensions.cs:line 396 at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\ResolutionExtensions.cs:line 244
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\ResolutionExtensions.cs:line 197
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\ResolutionExtensions.cs:line 181
at Autofac.Tests.Integration.Mef.SimpleRegistrationTests.DuplicateConstructorDependency() in c:\dev\opensource\autofac\trunk\Core\Tests\Autofac.Tests.Integration.Mef\SimpleRegistrationTests.cs:line 104

The inner exception stack trace actually points to where the MEF failure is occurring:

at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.EnsureGettable()
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.GetExportedValue(ExportDefinition definition)
at Autofac.Integration.Mef.RegistrationExtensions.<>c__DisplayClass1c.<>c__DisplayClass1e.b__15() in c:\dev\opensource\autofac\trunk\Core\Source\Autofac.Integration.Mef\RegistrationExtensions.cs:line 279
at System.ComponentModel.Composition.Primitives.Export.GetExportedValueCore()
at System.ComponentModel.Composition.Primitives.Export.get_Value()
at Autofac.Integration.Mef.RegistrationExtensions.<>c__DisplayClass1c.b__16(IComponentContext c) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac.Integration.Mef\RegistrationExtensions.cs:line 289
at Autofac.RegistrationExtensions.<>c__DisplayClass101.<Register>b__f(IComponentContext c, IEnumerable1 p) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\RegistrationExtensions.cs:line 231
at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass11.<ForDelegate>b__0(IComponentContext c, IEnumerable1 p) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Builder\RegistrationBuilder.cs:line 36
at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Activators\Delegate\DelegateActivator.cs:line 68 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\InstanceLookup.cs:line 79
at Autofac.Core.Resolving.InstanceLookup.Execute() in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\InstanceLookup.cs:line 62
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\ResolveOperation.cs:line 119 at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\InstanceLookup.cs:line 119
at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.b__0() in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Activators\Reflection\AutowiringParameter.cs:line 62
at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Activators\Reflection\ConstructorParameterBinding.cs:line 114
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Activators\Reflection\ReflectionActivator.cs:line 128 at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\InstanceLookup.cs:line 79
at Autofac.Core.Resolving.InstanceLookup.Execute() in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\InstanceLookup.cs:line 62
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\ResolveOperation.cs:line 119 at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\ResolveOperation.cs:line 67
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) in c:\dev\opensource\autofac\trunk\Core\Source\Autofac\Core\Resolving\ResolveOperation.cs:line 79

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on July 17, 2013 08:53:44

OK, I think I figured this out, but I'll need another set of eyes on it once I push the fix to make sure I didn't fix it in a way that will cause more issues.

The problem lies in the way exports and imports need to be set on things getting resolved [indirectly] through MEF.

A type registration gets converted to a 'ComposablePart' in a catalog. When you want an object based on a ComposablePart, you resolve the ComposablePart and then get its value. Dependencies are in the form of 'Exports' that get 'Imported' by the ComposablePart. Autofac basically has a lot of lambdas registered to automatically do Autofac resolution and populate the set of required import items on a ComposablePart so when you ask the part for its value, MEF wires things up and it all works.

The problem up being that if you ask for the same ComposablePart twice, the FIRST time you ask for it all the exports get wired up properly and it works; the SECOND time, it somehow skips the wireup of the exports and everything fails.

That was happening through an OnActivating event, but OnActivating didn't seem to want to fire for the particular unique ComposablePart more than once per resolution. Which makes sense, as technically a single instance (during the resolution process) is only getting activated the one time. Unfortunately, we're actually returning different ComposablePart instances each time - they just happen to boil down to the same internal dependency instance.

SOOOOO I fixed it by setting the required imports as part of the actual activation lambda when exports get queried. That way it'll always happen.

What I'm afraid of is the possibility that during an individual resolution operation something may inadvertently get double-activated or something like that. All the unit tests pass, things seem to just work, but... it'd just be nice to see if someone else can look at it and make sure I didn't do something dumb.

I'll push the fix shortly.

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on July 17, 2013 08:57:26

This issue was closed by revision b1084276c9e8 .

Status: Fixed

@alexmg
Copy link
Member Author

alexmg commented Jan 22, 2014

From travis.illig on July 17, 2013 08:57:52

OK, pushed. Includes an update to the version info for Autofac.Integration.Mef so it can be released as needed.

@alexmg alexmg closed this as completed Jan 22, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant