Locating Exports for Objects Created After Compose

2020-07-17 16:24发布

问题:

I've got a very simple app with a single export and multiple imports for the same type.

After I call ComposeParts I can see that the import worked in the same class where I called ComposeParts from - the MyService property has been hooked up.

The problem is that I have another UserControl that needs access to MyService and the property isn't set - it's in the same package etc. but it's not instatiated at the time I call ComposeParts.

If I make my CompositionContainer public / static and call ComposeParts and pass the UserControl the MyService property is set but that's a horrible solution.

Can anyone shed some light on what's going on? Is ComposeParts only smart enough to hook up existing objects or will an Import attribute be able to work on objects at a later time? Did I hook something up incorrectly?

public partial class App : Application    
{

  protected override void OnActivated(EventArgs e)
  {
    AssemblyCatalog assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
    compositionContainer = new CompositionContainer(assemblyCatalog);
    compositionContainer.ComposeParts(this);
  }

  [Import(typeof(MyService))]
  public MyService MyService { get; set; }
}

Update:

I'm trying to upgrade a 250k line C# prject from the Service Provider Model found in .Net 2.0 to MEF.

It doesn't seem like you can have a new object instance automatically be hooked up to the services it requires solely through the Import attribute. It seems like you need to re-trigger the ComposeParts or something like that. Lame.

In the .Net 2.0 provider/container model you needed to explicitly add child objects to parent containers and finding a service would be a recursive check from children to parents containers. I'm not sure what the corrolary is in MEF??

回答1:

One thing that looks like an issue is that you have only one assembly in your catalog (the executing assembly). If this is a single-assembly project where all the [Export] items are in the same assembly, then it will work fine. If not, then you'll need to pass all the assemblies into the catalog or use a DirectoryCatalog.

You can mark the UserControl classes with [Export], then instead of calling their constructors, you can use CompositionContainer.GetExportedValue() to create the UserControl and fulfill all its [Import] needs in one go. However, this is not always feasible with UI's if the forms already have the controls on there at design-time. In this case, you'll have to call ComposeParts to setup the [Import] values.

It really boils down to how you are setting up the UserControl classes in the application. If you wire it up at runtime, then you have a chance to hook into the CompositionContainer to create the instances for you and wire them up automatically. If you are relying on design-time code to set up the controls, then you will need to replace all your GetService() calls with ComposeParts() calls.



回答2:

You can check out dI.Hook framework on Codeplex for dynamic hooks

Link: http://dihook.codeplex.com/



标签: c# .net mef