开发者

Serializing Configurations for a Dependency Injection / Inversion of Control

I've been researching Dependency Injection and Inversion of Control practices lately in an effort to improve the architecture of our application framework and I can't seem to find a good answer to this question. It's very likely that I have my terminology confused, mixed up, or that I'm just naive to the concept right now, so a开发者_JS百科ny links or clarification would be appreciated.

Many examples of DI and IoC containers don't illustrate how the container will connect things together when you have a "library" of possible "plugins", or how to "serialize" a given configuration. (From what I've read about MEF, having multiple declarations of [Export] for the same type will not work if your object only requires 1 [Import]). Maybe that's a different pattern or I'm blinded by my current way of thinking.

Here's some code for an example reference:

public abstract class Engine {
}

public class FastEngine : Engine {
}

public class MediumEngine : Engine {
}

public class SlowEngine : Engine {
}

public class Car
{
    public Car(Engine e)
    {
        engine = e;
    }

    private Engine engine;
}

This post talks about "Fine-grained context" where 2 instances of the same object need different implementations of the "Engine" class: IoC.Resolve vs Constructor Injection

Is there a good framework that helps you configure or serialize a configuration to achieve something like this without hard coding it or hand-rolling the code to do this?

public class Application
{
    public void Go()
    {
        Car c1 = new Car(new FastEngine());
        Car c2 = new Car(new SlowEngine());
    }
}

Sample XML:

<XML>
    <Cars>
        <Car name="c1" engine="FastEngine" />
        <Car name="c2" engine="SlowEngine" />
    </Cars>
</XML>


I don't know about mef, but Spring does exactly what you describe using pretty much exactly the same method you describe (injection configured by an XML file or config section):

<objects>
  <object name="FastCar" type="MyApp.Car">
    <constructor-arg>
       <ref object="FastEngine">
    </constructor-arg>
  </object>
  <object name="SlowCar" type="MyApp.Car">
    <constructor-arg>
       <ref object="SlowEngine">
    </constructor-arg>     
  </object>
  <object name="FastEngine" type="MyApp.FastEngine"/>
  <object name="SlowEngine" type="MyApp.SlowEngine"/>
</objects>


Most DI Containers support XML configuration - in fact, most of them started out that way, and XML configuration was the only option. Nowadays, XML configuration is one option among several.

However, in it's current incarnation, MEF doesn't use XML configuration. It's not a DI Container either.


Using MEF (which you mentioned), you can use [ImportMany] to import a collection of Engine instances. You'd then be able to create one car per engine, and return that, with no XML required.

public class Application
{
    [ImportMany]
    public IEnumerable<Engine> Engines { get; set; }

    public void Go()
    {
        // I'm assuming this object was composed already...

        var cars = this.Engines.Select(e => new Car(e));

        foreach(var car in cars)
        {
            // Do something with each car
        }
    }
}

This has the advantage of allowing you to add new "Engines" any time, without changing your code. All of the wiring is handled dynamically at runtime without configuration.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜