使用Caliburn Micro Dependency Injection和自定义ModernUI ContentLoader

时间:2014-01-23 18:59:00

标签: c# dependency-injection caliburn.micro

我刚开始在我的wpf应用程序中使用Cliburn Micro。我开发使用依赖注入,以帮助使用接口保持抽象。

如何使用Caliburn Micros Bootstrappers容器来实例化我自己的类实例。

例如

public interface IFoo
{
    int ReturnNumber();
}

public class Foo : IFoo
{
    public int ReturnNumber()
    {
        return 1;
    }
}

public class SomeViewModel()
{
    public SomeViewMode()
    {
        IFoo = //instance from caliburn
    }
}

在我的引导程序中,我正在使用CompositionContainer

---- UPDATE ------

我正在并排使用Modern UI和Caliburn Micro框架,但当引导程序尝试解析包含参数的类型的实例时,在GetInstance(Type,String)方法的引导程序中获取空值异常IWindowManager。我相信这是由于ModernUI采用View第一种方法使用内容加载器与Caliburn.Micro进行通信的本质,但是我很难找到一个允许我的引导程序正常运行的解决方案。

以下是引导程序的配置

    public class AppBootstrapper : Bootstrapper<IShellViewModel>
{
    private static CompositionContainer _container;
    ....

    protected override void Configure()
    {
        // Add New ViewLocator Rule
        ViewLocator.NameTransformer.AddRule(
            @"(?<nsbefore>([A-Za-z_]\w*\.)*)?(?<nsvm>ViewModels\.)(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)(?<suffix>ViewModel$)",
            @"${nsbefore}Views.${nsafter}${basename}View",
            @"(([A-Za-z_]\w*\.)*)?ViewModels\.([A-Za-z_]\w*\.)*[A-Za-z_]\w*ViewModel$"
        );

        _container = new CompositionContainer(
                new AggregateCatalog(
                new AssemblyCatalog( typeof( IShellViewModel ).Assembly ),
                AssemblySource.Instance.Select( x => new AssemblyCatalog( x ) ).OfType<ComposablePartCatalog>().FirstOrDefault()
            )
        );

        var batch = new CompositionBatch();
        batch.AddExportedValue<IWindowManager>( new WindowManager() );
        batch.AddExportedValue<IEventAggregator>( new EventAggregator() );
        _container.Compose( batch );
    }

    protected override object GetInstance( Type serviceType, string key )
    {
        string contract = string.IsNullOrEmpty( key ) ? AttributedModelServices.GetContractName( serviceType ) : key;

        var exports = _container.GetExportedValues<object>( contract );
        return exports.FirstOrDefault();
    }

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:1)

您可以通过构造函数注入注入您的依赖项(假设它是必需的依赖项):

public class SomeViewModel : Screen
{
    private readonly IFoo foo;

    public SomeViewModel(IFoo foo)
    {
       // Can use foo later, e.g. in OnActivate for your screen
       this.foo = foo;            
    }
}

Caliburn.Micro通用引导程序通过配置的容器解析您的根视图模型(例如ShellViewModel)。如果SomeViewModelShellViewModel的依赖项,那么它的所有依赖项也将由容器和任何进一步链接的依赖项解析。

如果您希望控制类型的生命周期,请注入一个在您的容器中注册的工厂,并通过工厂创建该类型的新实例。

答案 1 :(得分:1)

好的,我找到了这个问题的解决方案,所以我想把它发布给任何其他人。通过defualt Caliburn.Micro查找一个默认构造函数,该构造函数不包含参数,但在类中不存在。因此需要使用[ImportingConstructor]属性来告诉caliburn micro使用注入来填充参数来构建类的实例。

使用devdigitals示例的示例

[ImportingConstructor]
public class SomeViewModel : Screen
{
    private readonly IFoo foo;

    public SomeViewModel(IFoo foo)
    {
       // Can use foo later, e.g. in OnActivate for your screen
       this.foo = foo;            
    }
}