Dynamically export constructor args from imported container

Jul 1, 2011 at 10:33 PM
Edited Jul 2, 2011 at 4:42 AM

I have a tricky situation and was hoping for some help.  Before the Lazy import is evaluated (i.Value) I was trying to export the Constructor parameters (IConstructParameters) that will be required by [ImportingConstructor].  In my attempt I have come across some issues.

1)  How do I get a reference to the container so I can call ComposeExportedValue.  The container is defined in class I do not wish to reference to maintain separation of concerns.  This must be a common issue but how do you use [Import] to get a reference to the container itself?

2) If all this were to work I would be calling ComposeExportedValue repeated (foreach loop), but only desire one constructParameter.  Would each loop overwrite the exported IConstructParameters in the container, 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 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<Contract, IMetaData> i in operations)
    {

     // Use Metadata to find desired export
     if (i.Metadata.MyData.Equals("TestString"))
        {
        //Just now able to figure out correct consturctParameters, so export before part is composed (i.Value).
        ?container?.ComposeExportedValue<IContructParameters>(constructParameters);
        i.Value.Start();
        }
}

Aug 1, 2011 at 10:42 PM

For (1) - you don't. We do not allow parts to access or modify the container they are in, as this significantly increases the fragility of the composition. Your host can call container.ComposeExportedValue<CompositionCOntainer>(container) and then your parts can import that, but we very much recommend against that

for (2) - Each call to ComposeExportedValue<> will add a new instance of IConstructParameters

(3) - this won't work. Aside from the fragility issue, most likely the part that imports "operations" will get rejected, as MyExportsClass will get rejected. With rejection on (which in .Net 4.0 is always is), we will "preview" the transitive closure of imports before we even try to activate the part. In your case, the absence of IConstructParameters will cause MyExportClass to disappear.

 

Based on what you have described, you are attempting some variation of contextual activation where the importer provides the exporter with addition data. We don't support this sort of dynamicity. I would recommend making that an explicit contract - e.g instead of importing MyExportClass, you would have MyExportClassFactory with Create(IConstructParameters). You will import that, and supply your argument as a function parameter.

Hope this helps

Oleg