0

Using Unity / Bootstrapper, I'm registering my base class - ServiceBase to multiple concrete services.

container.RegisterType<ServiceBase, ClearedPaymentService>("ClearedPaymentService");
container.RegisterType<ServiceBase, MissedPaymentService>("MissedPaymentService");

I'm also registering an external service below this:

container.RegisterType<IPaymentService, PaymentServiceClient>("PaymentService");

The external service is used in both the ClearedPaymentService and MissedPaymentService as shown below:

public partial class ClearedPaymentService : ServiceBase
{
    private readonly IPaymentService _paymentService;
    private readonly IScheduler _scheduler;
    private Timer _timer;

    public ClearedPaymentService(IPaymentService paymentService, IScheduler scheduler)
    {
        _paymentService = paymentService;
        _scheduler = scheduler;
    }

    ...etc
}

When I come to use my 2 services, I run into trouble:

var container = (IUnityContainer)Bootstrapper.Container;
var services = container.ResolveAll<ServiceBase>();

if (Environment.UserInteractive)
{
    RunInteractive(services.ToArray());
}

The code throws an exception on "services.ToArray()":

Resolution of the dependency failed, type = "System.ServiceProcess.ServiceBase", name = "ClearedPaymentService". Exception occurred while: while resolving. Exception is: InvalidOperationException - The current type, Think.IncomeProtection.ThirdParty.Service.Contract.Outbound.IPaymentService, is an interface and cannot be constructed. Are you missing a type mapping? At the time of the exception, the container was: Resolving ThirdPartyPaymentInvoker.ClearedPaymentService,ClearedPaymentService (mapped from System.ServiceProcess.ServiceBase, ClearedPaymentService) Resolving parameter "paymentService" of constructor ThirdPartyPaymentInvoker.ClearedPaymentService(Think.IncomeProtection.ThirdParty.Service.Contract.Outbound.IPaymentService paymentService, ThirdPartyPaymentInvoker.IScheduler scheduler) Resolving Think.IncomeProtection.ThirdParty.Service.Contract.Outbound.IPaymentService,(none)

I understand what the error is saying - the constructor of ClearedPaymentService is expecting a concrete instance of IPaymentService, but it hasn't been resolved for some reason...

I'm fairly new to Unity, so presume it's something basic that I haven't understood yet!

Any help appreciated.

Thanks, Alex

Al Hunter
  • 131
  • 1
  • 2
  • 8

1 Answers1

2

Your registrations to container provide a name for each service that is registered. So basically there is no default (not named) service that Unity can use in your scenario.

To fix this just remove the names while registering thins. If on other hand you wish to use specific named service then there is an attribute that you can add on parameter of your constructor [NamedDependancy("Your name")]. But by default you should not use this feature the code is simpler without it.

Rafal
  • 12,391
  • 32
  • 54
  • Thank you for the response, I purposefully added the named instances, as ResolveAll() doesn't resolve if I don't. "Enumeration yielded no results" – Al Hunter Jun 24 '14 at 11:42
  • Yes that is true. But will you resolve `IPaymentService` by this manner? if not then name is not necessary. If so you can add second registration without name just to fill the default one. – Rafal Jun 24 '14 at 12:04
  • 3
    One warning about the `[NamedDependency]`. This couples your code to Unity which is typically a bad thing. And the need for a `[NamedDependency]` is an indication of a [LSP](https://en.wikipedia.org/wiki/Liskov_substitution_principle) violation and ambiguity in the design of your application. In your case it is clear that you simply need a nameless registration. In other cases, you might be missing an abstraction to make the distinction clear between two two types (instead of using [NamedDependency]). – Steven Jun 24 '14 at 12:25
  • Great stuff! - Thanks for the help. I added the named versions to my services, but removed the name from the IPaymentService, which fixed the issue. – Al Hunter Jun 24 '14 at 12:36