在Caliburn Micro WPF应用程序上更改IoC提供程序

时间:2014-05-24 13:28:59

标签: ninject mef caliburn.micro

我有一个基于caliburn micro MVVM模式的现有WPF应用程序,它使用Ideablade / cocktail访问数据库。现在我已经切换到servicestack,我只是为了组合模式而保持鸡尾酒。因为我注意到启动应用程序需要相当长的时间,所以我做了一些测试,Ninject表现得更好。 我发现定义Export / ImportingConstrucor方法的MEF方法非常有用,但我想知道如何使用Ninject来实现它...是否可能?

在我目前的实施中,我有点像

[Export(typeof(IMyInterface))]
[Export(typeof(MyFirstViewModel))]
public class MyFirstViewModel:IMyInterface
{
    [ImportingConstructor]
    public MyFirstViewModel(IEventAggregator eventAggregator)ù
    {
    }
}

我发现在ninject中我要将某些内容定义为

 mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();
 mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();

可以自动吗? 我还可以定义一个功能,以便在找不到时解决吗?

由于

StackTrace :
 at Caliburn.Micro.IoC.<.cctor>b__0(Type service, String key) in c:\Users\Rob\Documents    \CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 13
 at Caliburn.Micro.IoC.Get[T](String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 32
 at myApp.Modules.Core.Framework.ViewModels.myAppScreenBase`1..ctor() in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels\myAppScreenBase.cs:line 44
 at myApp.Modules.Core.Framework.ViewModels.myAppSimpleScreen`1..ctor() in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels\myAppSimpleScreen.cs:line 8
 at myApp.Modules.AdE.ViewModels.CMATCLIDDelegheViewModel..ctor(IAdERepository repository, IDialogManager dialogManager, ICommonRepository commonRepository) in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Modules.AdE\ViewModels\CMATCLIDDelegheViewModel.cs:line 56
 at DynamicInjector1033b54d439c44dbaa064db1c7e82f18(Object[] )
 at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
 at Ninject.Activation.Context.ResolveInternal(Object scope)
 at Ninject.Activation.Context.Resolve()
 at Ninject.KernelBase.<>c__DisplayClass15.<Resolve>b__f(IBinding binding)
 at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
 at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
 at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

RepositoryExport:

public class RepositoryBindingGenerator : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {

        foreach (var attribute in type.GetCustomAttributes(typeof(RepositoryAttribute), false)
            .OfType<RepositoryAttribute>())
        {
            yield return bindingRoot
                            .Bind(attribute.ContractType ?? type)
                            .To(type).InSingletonScope();
        }


    }
}

但是我收到了这个编译错误

错误19无法将类型'Ninject.Syntax.IBindingNamedWithOrOnSyntax'隐式转换为'Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax'。存在显式转换(您是否错过了演员?)

1 个答案:

答案 0 :(得分:2)

根据ninject的配置(默认情况下已启用),您不需要将类型绑定到自身,ninject会自动解析它。所以mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();是多余的。备注:无论如何创建绑定也有效。

但是,如果要将Bar绑定到IFooFoo绑定到IFoo,则需要绑定它。 有了它,您可以告诉ninject查找具有[Export]属性的所有类型并绑定它们。 救援人员ninject conventions extension来了。获取ninject.extensions.conventions nuget包。

然后创建一个约定绑定:

kernel.Bind(x => x
                .FromThisAssembly()
                .SelectAllClasses()
                .WithAttribute<ExportAttribute>()
                .BindWith<ExportBindingGenerator>());

public class ExportBindingGenerator : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        foreach (var attribute in type.GetCustomAttributes<ExportAttribute>())
        {
            yield return bindingRoot
                            .Bind(attribute.ContractType)
                            .To(type);
        }
    }
}

当你需要使用[ImportingConstructor]属性告诉ninject使用哪个构造函数时,事情会变得复杂一些。但是我认为你不需要它,因为Ninject的auto-constructor-selection。但是,您可以使用Ninject的[ImportingConstructor]属性替换所有[Inject]属性,这些属性完全相同。

注意:

  • 您可能需要使用除.FromThisAssembly()之外的其他方法来指定包含实现类型的所有程序集。
  • 如果实现类型不公开,则需要将IncludeNonePublicTypes()添加到约定中。