2010-09-15 37 views
9

Tôi đang cố gắng để đưa một phụ thuộc vào bộ điều khiển MVC của tôi như thế nàyUnity Khung IoC với constructor mặc định

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

Lớp UserService có một constructor như thế này ...

public UserService(): this(new UserRepository(), new FacebookService()) 
{ 
    //this a parameterless constructor... why doesnt it get picked up by unity? 
} 

public UserService(IUserRepository repository, IFacebookService facebook_service) 
{ 
    Repository=repository; 
    this.FacebookService=facebook_service; 
} 

Trường hợp ngoại lệ Tôi đang nhận được như sau ...

Loại hiện tại, Repositories.IUserRepository, là một giao diện và không thể được xây dựng . Bạn có thiếu kiểu ánh xạ không?

Có vẻ như nó đang cố gắng đưa một nhà xây dựng vào dịch vụ, nhưng mặc định sẽ đủ? Tại sao nó không được ánh xạ tới hàm tạo parameterless?

+0

'Repository' và' this.FacebookService' là gì? – SwDevMan81

Trả lời

25

Quy ước mặc định thống nhất (được viết rõ ràng trong tài liệu) là chọn hàm tạo có nhiều tham số nhất. Bạn không thể thực hiện một tuyên bố chăn rằng "không đúng là IoC sẽ tìm ra hàm tạo cụ thể nhất, nếu bạn không chỉ định các tham số của hàm tạo trong khi đăng ký một kiểu, nó sẽ tự động gọi hàm khởi tạo mặc định." Mỗi triển khai vùng chứa có thể và có các giá trị mặc định khác nhau.

Trong trường hợp của Unity, như tôi đã nói, nó sẽ chọn hàm tạo có nhiều tham số nhất. Nếu có hai cái có nhiều tham số nhất thì nó sẽ mơ hồ và ném. Nếu bạn muốn một cái gì đó khác nhau, bạn phải cấu hình container để làm điều đó.

sự lựa chọn của bạn là:

Đặt [InjectionConstructor] thuộc tính trên các nhà xây dựng bạn muốn gọi (không khuyến khích, nhưng nhanh chóng và dễ dàng).

Sử dụng API:

container.RegisterType<UserService>(new InjectionConstructor()); 

Sử dụng XML config:

<container> 
    <register type="UserService"> 
    <constructor /> 
    </register> 
</container> 
+0

Thật đáng tiếc ngay cả Lâu đài Windsor đã chọn nhà xây dựng phù hợp nhất và Unity vẫn không thể. –

+0

Đó là một sự cân nhắc có chủ ý. Unity có thể giải quyết các loại bê tông không được đăng ký với container, Windsor không thể mà tôi biết. Điều này làm cho "phù hợp nhất" thực sự mơ hồ, vì vậy chúng tôi đã đi với một mặc định xác định hơn. –

+1

Cảm ơn bạn đã làm rõ. Tôi thấy bình luận của tôi có chứa các đối số mạnh không cần thiết. Đó nên là "Đơn vị không tự động chọn constructor" thay vì "không thể" :) Hình như họ đã chọn con đường khác bởi quyết định thiết kế cũng http://stackoverflow.com/a/499675/929902 Dù sao tôi hài lòng với Unity và với đó là sự linh hoạt. –

0

Tôi không thể nói chuyện với Unity một cách cụ thể, nhưng các thùng chứa IoC thường sẽ cố gắng sử dụng hàm tạo cụ thể nhất mà họ có thể tìm thấy vì nó là một hàm tạo.

Nếu có một hàm tạo phải mất hai phụ thuộc để tiêm, thì có lẽ chúng được yêu cầu để sử dụng đối tượng; constructor mặc định sẽ phải làm một cái gì đó để hoàn thành chúng nếu container gọi nó. Công việc của container là hoàn thành các phụ thuộc, vậy tại sao nó lại để cho lớp học làm điều đó nếu nó không được hướng dẫn để rời khỏi lớp học?

Đối với câu hỏi cụ thể của bạn, theo mã của bạn:

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

IUserRepository không được đăng ký. Thêm một dòng như

.RegisterType<IUserRepository, UserRepository>() 
+0

không đúng là IoC sẽ tìm ra hàm tạo cụ thể nhất, nếu bạn không chỉ định tham số của hàm tạo trong khi đăng ký một kiểu, nó sẽ tự động gọi hàm tạo mặc định. – TalentTuner

+0

Tôi không biết bạn đã sử dụng vùng chứa nào, nhưng tôi hầu như không bao giờ chỉ định các hàm tạo trong ánh xạ của tôi. Tôi biết chắc rằng StructureMap sẽ thích một constructor hoàn thiện hơn cho constructor mặc định - tôi đang sử dụng nó trong dự án hiện tại của mình, và đó là cách tôi kiểm tra một số đối tượng phải có một constructor mặc định (WCF Services)). Tôi khá chắc chắn rằng lâu đài Windsor cũng sẽ thích một nhà xây dựng cụ thể hơn. – arootbeer

+1

@saurabh Trong kinh nghiệm của tôi với Unity, khi không có tham số nào được chỉ định thì hàm tạo cụ thể nhất được sử dụng. –

Các vấn đề liên quan