GetExportedValue cannot be called before prerequisite import has been set
Asked Answered
G

1

7

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, however 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 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;
    }
}
Gird answered 23/1, 2014 at 13:24 Comment(2)
What is IMyAttributeInterface (MySubClass.Exports)? Does it have any relation with IMyInterface (MyMainClass)?Spiderwort
@PanosRontogiannis IMyAttributeInterface it is the type I am exporting. It has no relation with any of the classes there.Gird
N
0

Since the exception is thrown on your call of export.Value at a lazy export, that gives you an idea of what's going wrong.

The lazily imported export is not constructed until that point - it is merely 'discovered' and it's metadata is obtained. Once you call for its Value though, the lazy export needs to be actually instantiated.

At that point, its DLL will be loaded (so you might get an exception if you're missing any dependencies here, but that's not your problem) and the exported class will be constructed to satisfy the import in MySubClass. If the export needs another import (either through ImportingConstructor or separate Import), then it will try to resolve/instantiate that and so on.

I think the most likely reason you're getting the exception is not your MainClass or the SubClass, but the imports in your SubClass. Do they have any dependencies they're importing? Are those being resolved correctly? Try to investigate there.

Also be sure to check the InnerExceptions in the Exception that you've caught! It often goes down the rabbit hole of the whole importing chain until it reaches the point where it actually failed.

Nerveracking answered 25/11, 2020 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.