简体   繁体   中英

MEF and factories, import created object directly

I've started working with MEF. In my application I've a factory for some Models. My factory has 2 create methods; one takes a name as parameter, the other a type.

[Export(typeof(IFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyFactory : IFactory
{
    public IModel Create(String name) {...}
    public IModel Create(Type type) {...}
}

public class Foo
{
    [Import(typeof(IFactory))]
    public IFactory Factory { get; set; }

    public Foo()
    {
        IModel modelByName = Factory.Create("name");
        IModel modelByType = Factory.Create(typeof(Foo));
    }
}

At the moment I've to import a factory and then call create on the factory object to get a model. Now I'm wondering if there is a way to import a model directly, something like:

[Import(typeof(IModel), Name:"Name")]
public IModel Model { get; set; }

edit ---------------------------------------------------

The goal would be to replace something like this:

public class Foo
{
    [Import(typeof(IFactory))]
    public IFactory Factory { get; set; }

    public IModel Model { get; set; }
    public IModel Model1 { get; set; }

    public Foo()
    {
        Model = Factory.Create("Foo");
        Model1 = Factory.Create(typeof(Foo1));
    }
}

Whit something like this:

public class Foo
{
    //Should internal import a IFactory(singeleton) object 
    //and call the Create(name:String) method on it
    [Import(typeof(IModel), Name:"Foo")]
    public IModel Model { get; set; }

    //Should internal import a IFactory(singeleton) object 
    //and call the Create(type:Type) method on it
    [Import(typeof(IModel), Type: typeof(Foo1))]
    public IModel Model1 { get; set; }
}

You can't pass parameters of the [Import] attribute to methods of the type being imported.

I think you should not do so if you could however, because doing an import like that causes your class to be constructed and it'll most likely be prematurely constructed. You should delay construction of the object until the time it is actually needed. By doing a direct import, you lose this lazy behavior.

Also, a factory typically requires some parameters to construct a type, but this is not the case here. If you absolutely have to have the direct import, you can just import the type itself, instead of the factory (of course you'll lose the option of later on manipulating the construction easily by changing the factory's behavior).

You can add contract names to your exports and then use them when you import a part.

For the IModel interface:

public interface IModel { }

You can export an implementation as an IModel using a contract name:

[Export("Foo1", typeof(IModel))]
public class Foo1 : IModel { }

You can also add more than one export attributes on a single class. This way you can satisfy both kind of imports (by name and by type).

[Export("Foo2", typeof(IModel))]
[Export(typeof(Foo2))]
public class Foo2 : IModel { }

Then you import like this:

public class Foo
{
    //Import using the contract name.
    [Import("Foo1", typeof(IModel))]
    public IModel Model1 { get; set; }

    //Import using the actual type.
    [Import(typeof(Foo2))]
    public IModel Model2 { get; set; }

    //Import the same model but with contract name instead of type. 
    //This is possible because there are two different exports.
    [Import("Foo2")]
    public IModel Model3 { get; set; }
}    

As you can see you do not have to use ant factory at all. MEF will be your factory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM