Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parameters MEF+;MVVM:如何使用非导入或混合参数实例化类_Parameters_Constructor_Viewmodel_Mef_Factory - Fatal编程技术网

Parameters MEF+;MVVM:如何使用非导入或混合参数实例化类

Parameters MEF+;MVVM:如何使用非导入或混合参数实例化类,parameters,constructor,viewmodel,mef,factory,Parameters,Constructor,Viewmodel,Mef,Factory,我一直在试验MEF和MVVM。我想让MEF使用字符串构造函数参数初始化非共享ViewModel实例,例如: // BarViewModel's constructor has one single string parameter IBarViewModel bar = container.GetExportedValue<IBarViewModel>("bar title"); [Export(typeof(IBarViewModelFactory))] public class

我一直在试验MEF和MVVM。我想让MEF使用字符串构造函数参数初始化非共享ViewModel实例,例如:

// BarViewModel's constructor has one single string parameter
IBarViewModel bar = container.GetExportedValue<IBarViewModel>("bar title");
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
    [Import]
    public Lazy<CompositionContainer> Container { get; set; }

    public IBarViewModel CreateBarViewModel(string text)
    {
        IBarViewModel result = null;
        var tempContainer = CreateTemporaryDisposableContainer(Container.Value);
        try
        {
            result = new BarViewModel(text);
            tempContainer.ComposeParts(result);
        }
        catch (Exception ex)
        {
        }
        finally
        {              
        }

        return result;
    }

现在我不知道如何用MEF实例化这个类。我想这是一种非常常见的情况,所以我想知道MEF是否能够处理这一问题?

有两种方法可以完成您希望执行的操作:

  • 创建一个工厂并将所有必要的部分导入工厂,然后将其传递给类的构造函数。为此,您必须让工厂了解实现
    IBarViewModel
    接口的不同类以及它们实例化所需的部分,或者使用反射将它们放入一些列表中
BarViewModelFactory:

IBarViewModel实现:


  • 或者,您可以利用
    ExportFactory
    。它是,和的一部分。请注意,ExportFactory无法实例化类并将参数传递到构造函数中,因此在创建实例后,必须通过设置属性(或调用方法)来使用
    文本。还有,这里是一些关于这个项目的信息
BarViewModelFactory:


对于这两种情况,我都选择使用字符串文本来区分
SuperBarViewModel
(“x”)和
BarViewModel
(“”),但实际上您可以选择任何元数据来帮助选择一种

使用示例(适用于两种方案):



显然,除此之外,您还可以做很多事情,例如创建自己的自定义
ExportAttribute
,而不是使用默认的
ExportMetadataAttribute
进行元数据导出。这将允许您创建更复杂的元数据。此外,
SatisfyImports
/
SatisfyImportsOnce
是您需要了解的东西。基本上,您可以在此答案上展开以自定义您的解决方案。

MEF在.NET 4.0中,因此不支持开箱即用的ExportFactory。我正在使用格伦港口。谢谢,你的第一个解决方案比我的明显改进。
[Import]
public ILogger Logger {get;set;}

[ImportingConstructor]
public SomeClass(IDataService service, string text)
{
    Logger.Trace(text);
}
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
    [Import] private IServiceA ServiceA { get; set; }
    [Import] private IServiceB ServiceB { get; set; }

    // val is some metadata value to help decide which class to instantiate.
    public IBarViewModel CreateBarViewModel(string val, string text)
    {
        IBarViewModel result = null;

        try
        {
            // Select using metadata...
            if (String.Equals(val, "x", StringComparison.OrdinalIgnoreCase))
                result = new SuperBarViewModel(ServiceA, ServiceB, text);
            else
                result = new BarViewModel(ServiceA, text);
        }
        catch (Exception ex) { ... }
        finally { ... }

        return result;
    }    
}
public sealed class BarViewModel : ViewModelBase, IBarViewModel
{
    public BarViewModel(IServiceA svcA, string text)
    {
        ServiceA = svcA;

        // Do something with text, etc...
    }

    private IServiceA ServiceA { get; set; }
}

public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel
{
    public BarViewModel(IServiceA svcA, IServiceB svcB, string text)
    {
        ServiceA = svcA;
        ServiceB = svcB;

        // Do something with text, etc...
    }

    private IServiceA ServiceA { get; set; }
    private IServiceB ServiceB { get; set; }
}
[Export(typeof(IBarViewModelFactory))]
public class BarViewModelFactory : IBarViewModelFactory
{
    [ImportMany]
    private IEnumerable<ExportFactory<IBarViewModel, IBarViewModelMetadata>> Factories { get; set; }

    // val is some metadata value to help decide which class to return.
    public IBarViewModel CreateBarViewModel(string val, string text)
    {
        IBarViewModel result = null;

        try
        {
            result = Factories.Single(x => String.Equals(x.Metadata.Value, val, StringComparison.OrdinalIgnoreCase))
                              .CreateExport()
                              .Value;

            result.Text = text;
        }
        catch (Exception ex) { ... }
        finally { ... }

        return result;
    }
}
[ExportMetadata(typeof(IBarViewModel, ""))]
public sealed class BarViewModel : ViewModelBase, IBarViewModel
{
    [Import] private IServiceA ServiceA { get; set; }

    public string Text { get; set; }
}

[ExportMetadata(typeof(IBarViewModel, "x"))]
public sealed class SuperBarViewModel : ViewModelBase, IBarViewModel
{
    [Import] private IServiceA ServiceA { get; set; }
    [Import] private IServiceB ServiceB { get; set; }

    public string Text { get; set; }
}
[Export]
public sealed class SomeClass
{
    [Import]
    private IBarViewModelFactory BarViewModelFactory { get; set; }

    public void SomeMethod()
    {
        // Get the "Super" version by passing in "x" (metadata).
        var barVM = BarViewModelFactory.CreateBarViewModel("x", "my text");

        // etc...
    }
}