C# Ninject ActivationException:激活IAlertManagement时出错

C# Ninject ActivationException:激活IAlertManagement时出错,c#,ninject,tfsbuild,ninject-extensions,C#,Ninject,Tfsbuild,Ninject Extensions,我得到以下错误: Test method: BootStrapperTest.Can_Create_Alert_Management_Object threw exception: Ninject.ActivationException: Error activating IAlertManagement No matching bindings are available, and the type is not self-bindable. Activation path: 1

我得到以下错误:

Test method: BootStrapperTest.Can_Create_Alert_Management_Object threw exception:  Ninject.ActivationException: 
Error activating IAlertManagement No matching bindings are available, and the type is not self-bindable. 

Activation path:   
1) Request for IAlertManagement

Suggestions:    
1) Ensure that you have defined a binding for IAlertManagement.    
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.    
3) Ensure you have not accidentally created more than one kernel.    
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.    
5) If you are using automatic module loading, ensure the search path and filters are correct.
以下是导致此异常的测试用例:

[TestInitialize]
public void Initialize()
{
    BootStrapper.RegisterTypes();
}

[TestMethod]
public void Can_Create_Alert_Management_Object()
{
    IAlertManagement alertManagementService = BootStrapper.Kernel.Get<IAlertManagement>();

    Assert.IsNotNull(alertManagementService);
}

//This is the code that gets called in [TestInitialize]
public static void RegisterTypes()
{
    if (!initialized)
    {
        Kernel.Bind(scanner => scanner.FromAssembliesMatching("MyCompany.MyProduct.*")
                                   .SelectAllClasses()
                                   .BindDefaultInterface());

        Kernel.Unbind(typeof(IWcfServiceClient<>));
        Kernel.Bind(typeof(IWcfServiceClient<>)).ToMethod(ctx =>
                    (ctx.Kernel.Get(typeof(WcfServiceClientProvider<>).MakeGenericType(ctx.GenericArguments)) as IProvider).Create(ctx)); 
    }

    initialized = true;
}
[测试初始化]
公共无效初始化()
{
BootStrapper.RegisterTypes();
}
[测试方法]
public void可以\u创建\u警报\u管理\u对象()
{
IAlertManagement alertManagementService=BootStrapper.Kernel.Get();
Assert.IsNotNull(alertManagementService);
}
//这是在[TestInitialize]中调用的代码
公共静态无效注册表类型()
{
如果(!已初始化)
{
Bind(scanner=>scanner.fromsassembliesmatching(“MyCompany.MyProduct.*”)
.SelectAllClasses()
.BindDefaultInterface());
Unbind(typeof(IWcfServiceClient));
Kernel.Bind(typeof(IWcfServiceClient)).ToMethod(ctx=>
(ctx.Kernel.Get(typeof(WcfServiceClientProvider).MakeGenericType(ctx.GenericArguments))作为IProvider.Create(ctx));
}
初始化=真;
}
上述错误发生在我在构建服务器上的一个单元测试中,而不是在我的开发机器上。在构建服务器和我的开发机器上,我还有7个与此测试几乎相同的测试,通过了,但这是唯一失败的测试

IAlertManagement接口来自一个名为Core的dll,具体类型来自另一个名为AlertManagement的dll。我的单元测试项目中包含了核心dll和警报管理dll作为项目参考。我还有7到8个与这种情况相同的测试,但这是唯一一个失败的测试

任何想法都将不胜感激

  • 我要检查的第一件事是确保包含
    IAlertManagement
    实现的DLL被复制到构建服务器上的正确目录,以便测试可以看到它

  • 另一种尝试是将内核加载代码移动到
    ClassInitialize
    函数,而不是
    TestInitialize
    ,只是看看是否存在某种竞争条件或其他相关情况。我在构建服务器上看到过随机错误,这是由于对象的处理顺序不同或比正常情况下发生的时间更早(在我的案例中涉及Rx、TPL和未观察到的异常)。在构建服务器上并行运行的测试可能比在桌面上并行运行的测试多

  • 或者部分原因可能是服务器正在使用。我不知道强迫它使用WorkstationGC是否有帮助,但可能值得一试


  • 出现此错误的原因是
    IAlertManagement
    未与任何具体类绑定。 尝试手动绑定
    IAlertManagement

    public static void RegisterTypes()
    {
        if (!initialized)
        {
            Kernel.Bind(scanner => scanner.FromAssembliesMatching("MyCompany.MyProduct.*")
                                   .SelectAllClasses()
                                   .BindDefaultInterface());
    
    
            //Try to add following line
            Kernel.Bind<IAlertManagement>().To<ConcreteImplementationOfIAlertManagement>();
    
            Kernel.Unbind(typeof(IWcfServiceClient<>));
            Kernel.Bind(typeof(IWcfServiceClient<>)).ToMethod(ctx => (ctx.Kernel.Get(typeof(WcfServiceClientProvider<>).MakeGenericType(ctx.GenericArguments)) as IProvider).Create(ctx)); 
        }
    
        initialized = true;
    }
    
    publicstaticvoidregistertypes()
    {
    如果(!已初始化)
    {
    Bind(scanner=>scanner.fromsassembliesmatching(“MyCompany.MyProduct.*”)
    .SelectAllClasses()
    .BindDefaultInterface());
    //尝试添加以下行
    Kernel.Bind().To();
    Unbind(typeof(IWcfServiceClient));
    Bind(typeof(IWcfServiceClient)).ToMethod(ctx=>(ctx.Kernel.Get(typeof(WcfServiceClientProvider).MakeGenericType(ctx.GenericArguments))作为IPProvider.Create(ctx));
    }
    初始化=真;
    }
    
    我通过在单元测试项目中添加对解析类型的具体引用来解决这个问题。仅仅添加项目引用是不够的。我就是这样做的:

    [TestClass]
    public class AssemblyInitialize
    {
        /// <summary>
        /// Method which gets executed once per unit test session. The purpose of this method is to reference any loosely coupled
        /// assemblies so that they get included in the unit test session. If no code actually references a given assembly, even if its
        /// technically a project reference, it will not be copied to the test output folder.
        /// </summary>
        [AssemblyInitialize]
        public static void InitializeReferencedAssemblies(TestContext context)
        {
            List<Type> looselyCoupledTypes = new List<Type>
                                             {
                                                 typeof(AlertManagement),
                                                 typeof(Naming),
                                             };
    
            looselyCoupledTypes.ForEach(x => Console.WriteLine("Including loosely coupled assembly: {0}",
                                                               x.Assembly.FullName));
        }
    }
    
    [TestClass]
    公共类AssemblyInitialize
    {
    /// 
    ///方法,每个单元测试会话执行一次。此方法的目的是引用任何松散耦合的
    ///如果没有代码实际引用给定的程序集,即使其
    ///从技术上讲,它是一个项目引用,不会复制到测试输出文件夹。
    /// 
    [汇编初始化]
    公共静态无效初始化引用组件(TestContext上下文)
    {
    List looselyCoupledTypes=新列表
    {
    类型(警报管理),
    类型(命名),
    };
    ForEach(x=>Console.WriteLine(“包括松散耦合的程序集:{0}”),
    x、 (全名);
    }
    }
    
    这可能行得通,但这正是我首先想要摆脱的。我不想添加对所有具有具体类的dll的引用。我确实在生成服务器的drop文件夹中看到了包含
    IAlertManagement
    的dll。我还尝试将单元测试类切换为使用
    [ClassInitialize]
    而不是
    [TestInitialize]
    ,但似乎没有帮助。我没有探讨选项3。只是为了测试,试着将具体的AlertManagement放在一个你知道正在看到的程序集中,比如核心。例如,只需添加类的存根。然后你就会知道它是否只是找不到文件或者有其他东西。