2012-05-15 20 views
10

Tôi đang sử dụng Ninject.Extensions.Factory với Ninject 3 để tạo một nhà máy, tạo ra các loại khác nhau của IFoo dựa trên chuỗi cung cấp cho nhà máy. Tôi đã có một bài kiểm tra đơn vị vượt qua, nhưng kỳ quặc, chỉ trong Á hậu kiểm tra Resharper. Trong thử nghiệm NCrunch nó không thành công. Đây có phải là vấn đề về cấu hình NCrunch hay tôi cần phải thay đổi mã?Ninject ToFactory hoạt động trong các thử nghiệm đơn vị Resharper, nhưng không NCrunch

Giao diện:

public interface IFooFactory 
{ 
    IFoo CreateFoo(string name); 
} 

Các bindings Ninject:

kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstParameterAsNameInstanceProvider()); 
kernel.Bind<IFoo>().To<BarFoo>().Named("Bar"); 

Các thử nghiệm:

[Test] 
public void CanCreateFooTest() 
{ 
    var factory = (IFooFactory) Kernel.GetService(typeof(IFooFactory)); 
    var bar = factory.CreateFoo("Bar"); 
    Assert.AreEqual(typeof(BarFoo), bar.GetType()); 
} 

Và ngoại trừ NCrunch:

System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. 
    ----> Ninject.ActivationException : Error activating IInterceptor using conditional implicit self-binding of IInterceptor 
Provider returned null. 
Activation path: 
    2) Injection of dependency IInterceptor into parameter of constructor of type IFooFactoryProxy 
    1) Request for IFooFactory 

Suggestions: 
    1) Ensure that the provider handles creation requests properly. 

    at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) 
    at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) 
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) 
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
    at Ninject.Infrastructure.Language.ExtensionsForIEnumerable.ToArraySlow(IEnumerable series, Type elementType) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerable.cs:line 29 
    at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 149 
    at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 114 
    at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96 
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 
    at System.Linq.Buffer`1..ctor(IEnumerable`1 source) 
    at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) 
    at Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 95 
    at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 157 
    at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386 
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 
    at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source) 
    at Ninject.KernelBase.System.IServiceProvider.GetService(Type service) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 553 
    at FooProject.Tests.CanCreateFooTest() in C:\Projects\FooProject ... 
--ActivationException 
    at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 165 
    at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386 
    at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext() 
    at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext() 
    at System.Linq.Buffer`1..ctor(IEnumerable`1 source) 
    at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) 

Trả lời

6

Đây mã làm việc với NCrunch:

 var kernel = new StandardKernel(); 
     kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstParameterAsNameInstanceProvider()); 
     kernel.Bind<IFoo>().To<BarFoo>().Named("Bar"); 
     kernel.Load<FuncModule>(); 

     var factory = kernel.Get<IFooFactory>(); 
     var bar = factory.CreateFoo("Bar"); 
     Assert.Equal(typeof(BarFoo), bar.GetType()); 

CẬP NHẬT

này hoạt động tuyệt vời, và sắp xếp ra NCrunch. Tuy nhiên, Resharper phàn nàn rằng nó đã được tải hai lần. Cách giải quyết:

#if NCRUNCH 
     Kernel.Load<FuncModule>(); 
    #endif 
+3

tôi sẽ không tuyên bố đó là tốt hơn, nhưng cho đến khi Ninject cung cấp một cái gì đó giống như EnsureLoaded , một thay thế cho #if (nếu bạn muốn một cách tiếp cận khác) đang kiểm tra xem nó đã được tải thông qua Kernel.HasModule (typeof (FuncModule) .FullName) –

+0

Chúng tôi nhấn cùng một vấn đề trong một dự án mà chúng tôi tự động trích xuất tất cả các assembly (bao gồm cả ninject) từ các tài nguyên nhúng trong exe chính. Giải pháp này cũng hoạt động ở đây (tải thủ công 'FuncModule'). Trong trường hợp của chúng tôi, chúng tôi đã sửa nó bằng giải pháp @ JamesManning vì nó là một dll đã được sử dụng ở nhiều nơi. –

4

FuncModule không được nạp khi chạy với TestRunner đó. Điều này xảy ra trong trường hợp phần mở rộng không được sao chép vào thư mục khởi động của quá trình thực thi.

Tôi không NCrunch. Vì vậy, tôi không thể nói cho bạn biết nó đang làm gì. Nhưng rất có thể nó sao chép các hội đồng theo một cách khác với nhân vật thử nghiệm R #. Bạn có thể tải các tiện ích mở rộng theo cách thủ công nhưng điều này giống như một bản hack.

8

Đi vào cấu hình NCrunch cho thư viện đơn vị kiểm tra và thiết lập Sao chép cụm tham chiếu đến không gian làm việc để Đúng.

NCrunch confuguration screenshot

+0

+1 Giải pháp này hoạt động hoàn hảo cho tôi. Không chắc chắn nếu có một tác động hiệu suất lớn hay không. –

2

Tôi đã sử dụng đề xuất của harriyott trong một năm hoặc lâu hơn. Nhưng sau đó vấn đề này cũng xảy ra trên TFS-Buildserver của chúng tôi. Vì vậy, bây giờ tôi tránh Ninject tự động tải của tất cả các phần mở rộng và tải chúng bằng tay. Điều này tránh sự #if, #endif và cùng mã sẽ chạy trên Resharper và NCrunch:

var kernel = new StandardKernel(new NinjectSettings { LoadExtensions = false}); 
kernel.Load<FuncModule>(); 

phần còn lại là không thay đổi:

kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstParameterAsNameInstanceProvider()); 
kernel.Bind<IFoo>().To<BarFoo>().Named("Bar"); 

var factory = kernel.Get<IFooFactory>(); 
var bar = factory.CreateFoo("Bar"); 
Assert.Equal(typeof(BarFoo), bar.GetType()); 
Các vấn đề liên quan