2017-02-08 22 views
1

Я заметил этот интересный сценарий при попытке создать новое задание HangFire в моем приложении ASP.NET MVC.Castle.Windsor - почему имя должно быть похоже на интерфейс?

// this is the interface for the HangFire job. 
public interface ICsvExportService 
{ 
    void ExportCsvToEmail(); 
} 

// this is the implementation of the above interface. 
public class ExportService : ICsvExportService 
{ 
// code goes here. 
} 


RecurringJob.RemoveIfExists("My CSV exports"); 
     RecurringJob.AddOrUpdate<ICsvExportService>(
      "Send CSV exports", 
      x => x.ExportCsvToEmail(), 
      Cron.Daily(8)); 

В то время как я пытался проверить это на месте я получил ошибку ниже:

Exception не брошено: «Castle.MicroKernel.ComponentNotFoundException» в HangFire.Core.dll Нет компонент для поддержки услуги Была найдена ICsvExportService.

После 30 минут попыток различных решений я переименовал файл: ExportService в CsvExportService и произошло волшебство! Это сработало!

Может кто-нибудь объяснить, почему мне нужно использовать то же имя, что и интерфейс, чтобы контейнер DI распознал фактический класс реализации?

Castle.Core версия 3.3.3 для .NET 4.5 версия Castle.Windsor является 3.3.0 для .NET 4.5

Код для регистрации можно найти ниже:

container.Register(
      Classes.FromThisAssembly() 
       .Where(type => type.Name.EndsWith("Service")) 
       .WithServiceDefaultInterfaces() 
       .Configure(c => c.LifestyleTransient())); 

Многие Благодарю.

+0

Их нет; более чем вероятно, вы не зарегистрировали типы правильно с контейнером. Это просто предположение, потому что вы не показываете какой-либо код 'container.Register'. – Claies

+0

Я использую .WithServiceDefaultInterfaces(), который должен работать, но это не так. – Code4Fun

+0

нет, если вы прочтете ответ, который добавили @PatrickQuirk, использование 'DefaultInterfaces' именно в том, что вы видите поведение, которое вы описываете. вместо 'DefaultInterfaces', вы хотите' AllInterfaces'. – Claies

ответ

8

Вы не показываете, как вы регистрируете свои интерфейсы и классы, но, скорее всего, вы используете соглашение DefaultInterfaces.

Этот метод выполняет сопоставление на основе имени типа и имени интерфейса. Часто вы обнаружите, что у вас есть пары интерфейса/реализации, такие как: ICustomerRepository/CustomerRepository, IMessageSender/SmsMessageSender, INotificationService/DefaultNotificationService. Это сценарий, где вы можете использовать метод DefaultInterfaces для соответствия вашим услугам. Он будет рассматривать все интерфейсы, реализованные выбранными типами, и использовать в качестве служб типа те, у которых есть соответствующие имена. Соответствующие имена означают, что класс реализации содержит в своем имени имя интерфейса (без I спереди).

Есть целый ряд различных конвенций, но вы можете просто искать AllInterfaces:

Когда компонент реализует несколько интерфейсов, и вы хотите использовать его в качестве услуги для всех из них, использования WithService.AllInterfaces() способ.