【问题标题】:MEF and factories, import created object directlyMEF 和工厂,直接导入创建的对象
【发布时间】:2013-02-03 19:45:06
【问题描述】:

我已经开始使用 MEF。在我的应用程序中,我有一些模型的工厂。 我的工厂有 2 种创建方法;一个接受名称作为参数,另一个接受类型。

[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));
    }
}

目前我要导入一个工厂,然后调用 create 在工厂对象上获取模型。 现在我想知道是否有一种方法可以直接导入模型,例如:

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

编辑 ---------------------------------- -----

我们的目标是替换这样的东西:

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));
    }
}

类似这样的东西:

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; }
}

【问题讨论】:

    标签: c# import mef factory


    【解决方案1】:

    您不能将[Import] 属性的参数传递给所导入类型的方法。

    我认为,如果可以的话,您不应该这样做,因为进行这样的导入会导致您的类被构建,并且很可能会过早地构建。您应该将对象的构造延迟到实际需要的时候。通过直接导入,您将失去这种惰性行为。

    此外,工厂通常需要一些参数来构造类型,但这里不是这种情况。如果您绝对必须直接导入,则可以只导入类型本身,而不是工厂(当然,您将失去稍后通过更改工厂行为轻松操作构造的选项)。

    【讨论】:

    • 感谢您的回答。 ...我觉得我的问题不够准确我不想替换工厂,但是我想直接获取 Create 方法导入的返回值,所以我不必每次都创建一个因子,只是为了调用 Create 就可以了。
    【解决方案2】:

    您可以将合同名称添加到导出中,然后在导入部件时使用它们。

    对于IModel 接口:

    public interface IModel { }
    

    您可以使用合约名称将实现导出为IModel:

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

    您还可以在单​​个类上添加多个导出属性。这样您就可以满足两种类型的导入(按名称和类型)。

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

    然后你像这样导入:

    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; }
    }    
    

    如您所见,您根本不必使用 ant factory。 MEF 将成为您的工厂。

    【讨论】:

    • 为什么要使用dynamic关键字,我知道导入的对象是IModel类型。我正在寻找一种将属性放置在属性上并为该属性提供字符串或类型作为参数的方法。该属性现在应该将参数传递给 Create 方法,并将 Create 的返回值存储在属性中……我在问题中添加了一个伪示例。
    • 感谢您的回答。你是对的;如果我有一个用导出属性装饰的类,这将起作用。但是你看过编辑过的问题吗?工厂根据给定的字符串或类型做了一些重要的事情 (Create (type: Type), Create(name: String))... 有没有办法导入工厂创建的对象(注意:我应该能够在导入端指定字符串或类型)
    • @user1320170 那么我相信您真正需要的是一个 IoC 容器,例如 Autofac(顺便说一下与 MEF 集成)。有一种方法可以使用 MEF 执行此操作,但您必须添加另一层抽象,您的解决方案将变得复杂。而你打算在很多地方使用这种模式,那么情况会更糟。
    • 谢谢我去看看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多