Dynamically export constructor args from imported container

Jul 2, 2011 at 4:26 AM
Edited Jul 3, 2011 at 1:42 PM

I have run into a fundamental issue with my prism based application.  Just before the Lazy import is evaluated (i.Value) I must export the Constructor parameters (IConstructParameters) that will be required by [ImportingConstructor].  In my attempt I have come across the issues below.

1)  How do I get a reference to the container so I can call ComposeExportedValue.  The container is defined in the bootstrapper, and the class below should not depend on bootstrap in any way.  I could do an import on ServiceLocator (ie. [Import] IServiceLocator ServiceLocator;), but that cannot be used to call ComposeExportedValue.  Perhaps I am on the track with something like "((CompositionContainer)_MyServiceLocator).ComposeExportedValue<IMyExport>(myExport)"?

2) If all this were to work I would be calling the same ComposeExportedValue repeated (foreach loop).  Would each loop overwrite the same exported IConstructParameters in the container (desired), leaving only one constructParameter in the container at a given time?

3)  Please help with #1/2 regardless, but is this even the correct approach?  To summarize I am trying to dynamically export the constructorParameters just prior to the part being compose due to i.Value evaluation.  Creating a class and passing arguments to the constructor once was a trivial goal.

[Export(typeof(IContract)]
[ExportMetadata("MyData", "TestString")]
public class MyExportClass : IContract
{
     [ImportingConstructor]
     public MyExportClass(IConstructParameters constructParameters) {}
 
     public Start() {}
}


[ImportMany]
IEnumerable<Lazy<IContract, IMetaData>> operations;

public void UseImport ()
{
  foreach (Lazy<IContract, IMetaData> i in operations)
    {
     if (i.Metadata.MyData.Equals("TestString")) // Check Metadata to find desired export
        {
        // Just now able to figure out correct consturctParameters, so export before part is composed by "i.Value".

        ?container?.ComposeExportedValue<IContructParameters>(constructParameters);
        i.Value.Start();
        }
}

Thanks,

aidesigner

Jul 4, 2011 at 8:54 PM

Hi,

One possible way to obtain an instance to the Composition Container in your component would be to register the Composition Container, by overriding the ConfigureContainer’s method in the Boostrapper. Then you can access the container via the ServiceLocator. For example like this:

var container = ServiceLocator.Current.GetInstance(CompositionContainer);

Take into account that ServiceLocator (which, in your case, retrieves the instances from the MEF container) implements the necessary functionality to retrieve values from the container and hides the registering functionality since that is outside the scope of the functionality that is intended to be exposed through the IServiceLocator interface. Therefore, you shouldn’t cast the IServiceLocator instance to CompositionContainer.

I hope you find this information useful.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic

 

Jul 6, 2011 at 4:00 AM
Edited Jul 6, 2011 at 4:34 AM

Thank you for the reply and it answered question #1 perfectly.  Could I get a little more help with question 2 and 3, as I believe it could be beneficial to everyone!

Note:  My questions assume a just-in-time scheme for creating constructor parameters for use with [ImportConstuctor] exists.  In addition I presume the [ImportingConstructor] does not pull on the container until "i.Value" (Lazy) is evaluated.

Thanks,

Jul 7, 2011 at 7:30 PM

Hi,

As this is not strictly related to Prism, you might find better support in MEF Forums in Codeplex. Additionally, you might find MEF’s support in MSDN forums

On the other hand, you can check the MEF Programming Guide here.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic