【问题标题】:Changing IoC provider on an Caliburn Micro WPF Application在 Caliburn Micro WPF 应用程序上更改 IoC 提供程序
【发布时间】:2014-05-24 13:28:59
【问题描述】:

我有一个基于 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()

存储库导出:

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”。存在显式转换(您是否缺少演员表?)

【问题讨论】:

标签: ninject mef caliburn.micro


【解决方案1】:

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

但是,如果要将Bar 绑定到IFooFooIFoo,则需要绑定它。 有了它,您可以告诉 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。但是,您可以做的是将所有 [ImportingConstructor] 属性替换为 Ninject 的 [Inject] 属性,该属性完全相同。

注意事项:

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

【讨论】:

  • 您好 BatteryBackupUnit,我已经尝试过您的解决方案,它部分有效......部分原因是我忘记告诉您在某些 ViewModel 中我必须导出一个 ITaggable 接口和 viewmodel 本身,当我尝试解决 kernel.GetAll 我有一个异常告诉 IoC 尚未初始化.. 我该如何解决这个问题?谢谢
  • 您能否提供确切的例外情况?完成消息和 Stacktrace。
  • IoC 未初始化。 StackTrace:在 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:myApp.Modules.Core.Framework 的第 32 行.ViewModels.myAppScreenBase`1..ctor() 在 c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels\myAppScreenBase.cs:line 44
  • 在 c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels 中的 myApp.Modules.Core.Framework.ViewModels.myAppSimpleScreen`1..ctor() \myAppSimpleScreen.cs:第 8 行,位于 c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Modules 中的 myApp.Modules.AdE.ViewModels.CMATCLIDDelegheViewModel..ctor(IAdERepository 存储库,IDialogManager dialogManager,ICommonRepository commonRepository)。 AdE\ViewModels\CMATCLIDDelegheViewModel.cs:第 56 行在 DynamicInjector1033b54d439c44dbaa064db1c7e82f18(Object[]) 在 Ninject.Activation.Providers.StandardProvider.Create(IContext context)
  • 在 Ninject.Activation.Context.ResolveInternal(Object scope) 在 Ninject.KernelBase.c__DisplayClass15.b__f(IBinding binding) 在 Ninject.Activation.Context.Resolve() 在 System。 Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.&lt;CastIterator&gt;d__b11.MoveNext() 在 System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
相关资源
最近更新 更多