views:

203

answers:

3

Perhaps I'm misapplying Unity, but here goes. I have a couple of applications, both of which load the same plugin assemblies. All assemblies require a library, and I want them to be able to access this library via Unity. However, in order to use Unity, or any other IoC framework, I'd have to write an interface for this library. I will probably do this, but since an interface isn't really needed for anything other than to support Unity, I am afraid that this means that I am 1) missing the point, or 2) misapplying the framework. If I avoid something that offers me DI, then I'd have to make the library class a singleton, and then pass it to all of the plugin constructors, or via a public property, and I don't want to do this.

That said, and without actually implementing anything with Unity yet, I'm not getting one other detail -- although Unity will let me request the library via Resolve<>, my plugins will still need to have a reference to the Unity instance that is created in the main applications. So is this a case where your only option is to pass the Unity reference to all of the plugins, but then it's convenient from that point on, merely because you can use Unity to get at all of the other dependencies?

UPDATE

I realized that I missed the point, but hopefully someone can clarify for me -- I shouldn't be passing a ref to Unity everywhere! I should only have to create the container in my app, and then register all of the types afterward. Then when I instantiate all of my plugins, they should just magically be able to use those registered interfaces, with almost no extra effort, right? In my case, my constructors must be parameterless because my plugin loader can't deal with arguments, and in that case, I'll have to use property injection to give them access to the interfaces, right?

ANOTHER UPDATE

I went ahead and tried out Unity. I registered the instance of my class that's needed by all plugins. I also know that I would eventually run into a problem with my plugin loader since they are parameterless (and I might need to pass it a ref to Unity to make them work). However, just for now I am directly creating a plugin, and I am doing that via the Resolve method. So here's basically what the code looks like:

// app code
ICandySettings _candy_settings = new CandySettings();
IUnityContainer unity = new UnityContainer().RegisterInstance<ICandySettings>( _candy_settings);
CandyPlugin _plugin = unity.Resolve<Candy>(); // throws null reference exception, see below.

// plugin code
public class Candy
{
  [Dependency]
  ICandySettings CandySettings { get; set; }

  ...

  public Candy()
  {
    CandySettings.GetSetting("box"); // CandySettings is null!  why?  Didn't Unity do this for me?
  }
}

So my problem right now is that I would expect (given my limited knowledge), that Unity is going to automagically set the plugin's CandySettings reference to whatever instance was registered via RegisterInstance, but it's not.

A WORKING OPTION

If I skip the smoke and mirrors stuff and just pass my UnityContainer into the plugin's constructor, then I can call Unity.Resolve() to set the value of my CandySettings property, and everything works great. I'd love to know why the [Dependency] attribute isn't doing what I thought it would. If I'm not mistaken, I actually shouldn't need to pass Unity to each constructor in my plugin loader. I should just use Unity.Resolve() and it would presumably work if [Dependency] is working. However, now I understand what everyone is saying about how picking an IoC container will then force it on your entire development team.

MEF!

So far, MEF is winning the battle for me. It's pretty simple, and the magical smoke and mirrors stuff works great for my needs (currently). But I'd still like to get Unity working. I find it strange that for MEF, I only need to compose the parts and everything else just falls into place, whereas I can't seem to get Unity to just inject stuff automatically, and I have to Resolve everything through a reference to Unity passed everywhere. This can't be right.

More MEF

I like the idea that I can resolve multiple objects with MEF very easily, but what about cases where I'm using the Strategy pattern to dictate code behavior? Currently, it's as simple as changing the reference from one implementation of a behavior to another, and it just works. Does anyone do this with MEF? Is the right way to do it to use ImportMany, and then use extra code to determine which behavior in the list should get invoked?

+1  A: 

If your dependency injection requirements are minor (which, from the sounds of it, they are), you might want to consider trying MEF. This is lightweight and easy to use, and has the advantage of being in the framework directly in .NET 4, which means no extra requirements to deploy if you ever move to .NET 4.

In the interim, it's supported on 3.5 via the Codeplex site.

MEF is nice in this since it can work on any type, not just interfaces.

That being said, if you want plugins to use a "library" provided by your application, you're most likely going to always need that library to be available and referenced by your plugins (or at least a set of base classes or interfaces for the API).

Reed Copsey
I will check it out now. Thanks for the suggestion, Reed.
Dave
Reed, this sounds like a nice way to do plugins for my application, actually. Currently, I am using interfaces for the different plugin types and then my plugin loader looks through the assembly info to figure out what interfaces each plugin supports. MEF seems to do the same thing, but perhaps more cleanly. Am I understanding it correctly?
Dave
@Dave: Yes. It was designed specifically for extending applications (ie: plugins), although it's useful as a general purpose IoC option. MEF is really, really nice for plugin creation and composition, though.
Reed Copsey
@Reed: I'll give it a shot on a smaller test project. Would you mind looking at my flurry of updates to my original question and let me know what you think, especially of the [Dependency] attribute issues I'm seeing?
Dave
@Dave: I don't use Unity (it's a bit heavy-weight to me, and much more difficult than MEF, which is why I had suggested MEF), however, from what I remember, the main problem here is one of nearly all IoC containers. Unless you use constructor injection (ie: pass the parameters directly into the Constructor - MEF supports this, not sure about Unity), the container needs to construct your object FIRST, and only THEN, set all of the dependencies. In your case, this means that unity will create your object (and run your constructor), get back the object, then set CandySettings appropriately.
Reed Copsey
ah, I see! that does make some sense. perhaps I could defer usage of the CandySettings library, but I don't know right now. I've branched my code and am going to give MEF a try now. Thanks for the help!
Dave
@Reed: I have a MEF solution working, but not quite sure if it's right: http://stackoverflow.com/questions/2655209/mef-may-experience-frustration. I was going to ask you about lifetimes, but it looks like MEF is singleton by default. phew.
Dave
@Dave: I answered there. If you want non-singletons, you'll want to use ExportFactory<T>, btw. (See http://mef.codeplex.com/Thread/View.aspx?ThreadId=207539)
Reed Copsey
@Reed: ok, thanks! I will keep that in mind -- might need something like that for creating multiple instances of the same type of plugin, I think?
Dave
+1  A: 

Most IoC containers can map concrete classes as well as interfaces, it's just that using interfaces is considered by most to be a better practice as it relates to design and testing.

If all you want to do is allow provisioning of a few common types, you might want to roll your own using System.IServiceProvider. it's built-in so you wouldn't need to cascade your IoC dependencies to your consuming code.

public class SomePlugin
{
 public SomePlugin(IServiceProvider serviceProvider)
 {
  _foo = serviceProvider.GetService(typeof(IFoo)) as IFoo;
 }
}

Or you could have a singleton service locator as in the Common Service Locator library

public class SomePlugin
{
 public SomePlugin()
 {
  _foo = ServiceLocator.Current.GetService(typeof(IFoo)) as IFoo;
 }
}

EDIT: Given your updates, i'd suggest using BuildUp to inject property dependencies on your plugin instances after you've instantiated them. See this article

PluginInstance plugin = // already loaded from whatever you're already doing
container.BuildUp<PluginInstance>(plugin);
ray2k
that could also do the trick... I was going to use the service locator before, until I watched the Unity video and it sounded like a better way to go. But in this case, it might actually be the best solution for me. I'm going to keep working with Unity first though to understand how it works, then I'll revert back and try out the service locator.
Dave
man, System.IServiceProvider has to be one of the least documented interfaces I've seen thus far. Can you recommend any good sites that describe how to properly implement IServiceProvider.GetInterface()?
Dave
Hmm.. could it really be as simple as my class inheriting from IServiceProvider, then in GetService(), check the passed in Type and compare it to the Type of object I want to return, and if it matches, just return it? I will try this now to see what happens. But how does the derived IServiceProvider get registered with the ServiceLocator?
Dave
As far as the type-checking, yes. You could make it as simple or advanced as you want. As far as accessing the derived IServiceProvider, I think you're split between a few different options. You could1) Alter the plugin constructors to take an IServiceProvider instance. This is probably the easiest solution, as the plugins wouldn't need any additional dependencies.2)Make a class with a static instance of your IServiceProvider, which is set before the plugins use it. Your plugins will need a reference to whatever library has the static instance class in it.
ray2k
3) The same thing as 2) but using a read-write property on the plugin class which is of type IServiceProvider, which you'd set before interacting with the plugin instances. May require more updates to plugins than you care to make.4) Use the CommonServiceLocator library and write your own adapter. CSL has its own interface similar to IServiceProvider, and you can implement it and pipe it in to the static ServiceLocator.Current instance. Plugins would gain a dependency on CSL.If your stuff is as simple as you make it out to be, I'd just choose 1) and call it a day.
ray2k
In this case, it almost seems easier to use RegisterInstance with Unity to get everything working. Would you mind commenting on my updates to my original question? Thanks!
Dave
I don't have the rep for that, but I'd gather a guess that Resolve<> requires the type (Candy) to already be registered. Some containers have a way to inject dependencies into existing object instances regardless of being registered or not, maybe Unity does?EDIT: try creating a Candy instance, then calling container.BuildUp<Candy>(candyInstance)
ray2k
A: 

First, I have a singleton which holds a reference to my Unity container instance, so I don't have to pass it around everywhere.

Second, you are free to use unityContainer.RegisterInstance(myInstance); or unityContainer.RegisterType<MyClass, MyClass>();

Daniel Rose
Yeah, I'm using RegisterInstance in my case. I'm re-watching the Unity video from MS to see what I missed the first time around. I'm sure that once I get this working I'll be slapping myself for taking so long to get this going.
Dave