none
GetExportedValue cannot be called before prerequisite import has been set? RRS feed

  • Question

  • We are using MEF in a WPF application.

    And we are getting this error:

    GetExportedValue cannot be called before prerequisite import 'MyNamespace.MyMainClass..ctor (Parameter="myParameter", ContractName="IContractInterface")' has been set.

    I am not using threads, I read sometimes this error happens with multiple threads, just in case, I created the composition container passing the "thread safe" parameter in true

    var container = new CompositionContainer(catalog, true);

    The Code I have is:

    My simplified Main Class code is: (The idea is that if there are not import for IMySubClass, I will use a default Implementation, that is why I create it on the "OmImportsSatisfied" method and satisfy its imports.)

    MyMainClass C#

    [Export(typeof(IMyInterface)]
    public class MyMainClass: IPartImportsSatisfiedNotification, IMyInterface
    {
        [Import]
        public IContainer Container { get; private set; }
    
        [Import(AllowDefault = true)]
        public IMySubClass MySubClass { get; set; }
    
        [ImportingConstructor]
        public MyMainClass([Import(AllowDefault = true)] IContractInterface myParameter= null)
            : this()
        {
            if (myParameter!= null)
            {
                //Do Something with myParameter
            }            
        }
    
        public void OnImportsSatisfied()
        {
            if (MySubClass == null)
            {
                MySubClass = new MySubClass();
                Container.SatisfyImportsOnce(MySubClass);
            }
    
            //Some other stuff
         }

    }

    MySubClass C#

    public class MySubClass : IPartImportsSatisfiedNotification, IMySubClass { [ImportMany] public Lazy<IMyAttributeInterface, IMyAttributeInterfaceMetadata>[] Exports { get; set; }

        public MySubClass (IContractInterface myParameter= null)
            : this()
        {
            if (myParameter!= null)
            {
                //Do Something with myParameter
            }           
        }

    public void OnImportsSatisfied() { foreach (var export in Exports) { var value = export.Value; //Here it throws the Exception //Do something. } }

    The error is thrown in MySubClass, inside the OnImportSatisfied method on the line:

    var value = export.Value;

    However when I debug the ImportConstructor of MyMainClass is called successfully, and myParameter is injected and used. Afterwards the OnImportsSatisfied method is called and I get the error.


    The Exports list from my Subclass comes from properties in other classes that have the Attribute "MyExportAttribute". I don't have much experience creating Export Attributes, so here is the code in case the problem is coming from it.

    Export Attribute

    public interface IMyAttributeInterfaceMetadata
    {
        string Property1 { get; }
        string Property2 { get; }
    }
    
    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
    public class MyExportAttribute : ExportAttribute, IMyAttributeInterfaceMetadata
    {
        string Property1 { get; }
        string Property2 { get; }
    
        public MyExportAttribute(string property1, string property2)
            : base(typeof(IMyAttributeInterface))
        {
            Property1 = property1;
            Property2 = property2;
        }
    }

    Dzyann.-



    • Edited by Dzyann Wednesday, February 5, 2014 2:08 PM
    Wednesday, January 29, 2014 12:35 PM

All replies

  • Hello,

    Have a try to using Lazy instantiation to see whether it can help.

    See it here:

    http://stackoverflow.com/questions/3696893/mef-error-was-circular-dependency-and-is-now-something-else

    Thursday, January 30, 2014 3:13 AM
  • Hi AlpacaYou,

    As you can see I already have Lazy instantiation in the public Lazy<IMyAttributeInterface, IMyAttributeInterfaceMetadata>[] Exports of my SubClass, where else would you add Lazy?


    Dzyann.-

    Thursday, January 30, 2014 9:01 PM
  • Hello Dzyann,

    >>GetExportedValue cannot be called before prerequisite import 'MyNamespace.MyMainClass..ctor (Parameter="myParameter", ContractName="IContractInterface")' has been set.

    For this error, it may be caused by a circular dependency and one solution is to be lazy:

    [ImportingConstructor]

    public MainViewModel(Lazy<IBreadcrumbService> breadcrumbService)

    {

    //…

    }

    See details here.

    If I misunderstand, please let me know.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, February 3, 2014 7:56 AM
    Moderator
  • Hi Fred Bao,

    Sorry I couldn't come back to this post earlier. I don't think Lazy is the solution, yet I added lazy to absolutely everything. It still throws the exception.

    My situation is not the same than the one in the post you suggested to me.

    I have only an import constructor in MyMainClass, MySubClass doesn't have an ImportConstructor, it has an Standard constructor.

    However I made  IContractInterface myParameter, Lazy in both constructors.

    The error is happening in the OnImportsSatisfied of the second class (MySubClass). Checking the documentation of the IPartImportsSatisfiedNotification interface, the OnImportsSatisfied method gets "Called when a part's imports have been satisfied and it is safe to use".

    Steps:

    1. MyMainClass gets created by MEF, and the "IContractInterface parameter" gets passed along. I use it successfully.
    2. The OnImportsSatisfied of MyMainClass gets called.
    3. On the OnImportSatisfied of MyMainClass I created MySubClass and pass the "IContractInterface parameter", that I have already successfully used inside the MyMainClass constructor. I successfully use it also inside the MySubClass constructor.
    4. MySubClass gets created and successfully use the "IContractInterface parameter" I pass. Note I am creating it and not MEF.
    5. Then, inside the OnImportsSatisfied of MyMainClass, I satisfy the imports of MySubClass (Container.SatisfyImportsOnce(MySubClass);),
    6. Step 5 causes the OnImportsSatisfied of MySubClass to get called.
    7. Inside the OnImportsSatisfied of MySubClass I try to access the Exports (public Lazy<IMyAttributeInterface, IMyAttributeInterfaceMetadata>[] Exports )
    8. I get the exception. (when accessing Exports inside OnImportsSatisfied of MySubClass).

    The Exports (public Lazy<IMyAttributeInterface, IMyAttributeInterfaceMetadata>[] Exports )) should have been already satisfied (on 8) because that is when the OnImportsSatisfied gets called. Or at least the documentation says so.

    I guess the problem comes from the fact that the OnImportsSatisfied of the MySubClass get called in the middle of the OnImportsSatisfied of MyMainClass.

    But what doesn't make sense at all, is that if instead of receiving the "IContractInterface myParameter" in the Import constructor of the MyMainClass I directly import it and Use it in my OnImportsSatisfied like this:

    [Import(AllowDefault=true)] IContractInterface MyParameter {get;set;} public override void OnImportsSatisfied() { base.OnImportsSatisfied(); if (MyParameter != null) { //Use my parameter }

    if (MySubClass == null)
           
    {
               
    MySubClass = new MySubClass();
               
    Container.SatisfyImportsOnce(MySubClass);
           
    }

           
    //Some other stuff

    Everything works fine, without errors.

    Thanks in advance for your help.


    Dzyann.-

    Wednesday, February 5, 2014 2:26 PM
  • Is this a bug of MEF? If so where would you recommend I post this?

    Also why is that I constantly get my questions marked as answered when I haven't done it myself? They marked my previous post as an answer. It seems they didn't even read what I posted.

    I found a work around, it doesn't mean I solved the actual problem I am asking about.

    Please I need some help. Thanks!


    Dzyann.-

    Friday, February 7, 2014 5:46 PM