我有一个基于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'。存在显式转换(您是否错过了演员?)
答案 0 :(得分:2)
根据ninject的配置(默认情况下已启用),您不需要将类型绑定到自身,ninject会自动解析它。所以mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();
是多余的。备注:无论如何创建绑定也有效。
但是,如果要将Bar
绑定到IFoo
或Foo
绑定到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()
添加到约定中。