Dependency injection not resolving from other module

Topics: General, Installing Orchard, Troubleshooting
Jun 25, 2013 at 10:20 AM
Hi everyone,

I am trying to inject a service (PersonService) from another module into my main module.

The service was developed in the main module, and works just fine (including DI).
It inherrits from its interface (IPersonService) and this interface inherrits IDependency.

I am now refactoring so the implementation of the actual service resides in a separate Orchard module.
The main module has a dependency to the service module in the Module.txt
The interfaces for the service remains in the main module.
The service module has a reference (.net) to the main module (for the interfaces, modals,etc)

When running i get the exeption:
None of the constructors found with 'Orchard.Environment.AutofacUtil.DynamicProxy2.ConstructorFinderWrapper' on type 'SG.CustomerPortalTobias.Controllers.MyPageController' can be invoked with the available services and parameters:

Cannot resolve parameter 'SG.CustomerPortalTobias.Services.IPersonService service' of constructor 'Void .ctor(SG.CustomerPortalTobias.Services.IPersonService, SG.CustomerPortalTobias.Services.IAccountService, Orchard.UI.Notify.INotifier, Orchard.Caching.ICacheManager, Orchard.Caching.ISignals)'.

For some reason it is not getting resolved by autofac...
Dous anyone know what i am missing here?

If the answer is already somewhere here on this forum, i apologize for not searching correctly... :)



Kind Regards,
Richard Scholten
SG|automatisering
Emmen, the Netherlands
Developer
Jun 25, 2013 at 11:43 AM
Edited Jun 25, 2013 at 11:51 AM
Is the feature containing your service class enabled from the dashboard? If you refactored the code and added a new dependency to the already enabled (main) module Orchard won't auto-enable the new feature - you need to do it manually.
Jun 25, 2013 at 12:18 PM
Edited Jun 25, 2013 at 12:18 PM
May be stupid question but is your service class public ?
Jun 25, 2013 at 12:22 PM
Edited Jun 25, 2013 at 12:26 PM
pszmyd wrote:
Is the feature containing your service class enabled from the dashboard? If you refactored the code and added a new dependency to the already enabled (main) module Orchard won't auto-enable the new feature - you need to do it manually.
Yes i enabled it by disabling and re-enabling the main module.
The service module got enabled automaticly when enabling the main module (the dependency seems correct)

But what you are saying is that dependency injecten between Orchard modules should work this way? (I am new to dependency injection, mvc and Orchard...)
in other words: i am on the right track?

What i am trying to do is inject a service based on an interface (duh) that i can easily replace with another service based on the same interface.
The service does not necessarily have to be an Orchard module, but i figured its the correct (Orchard) thing to do.
Jun 25, 2013 at 12:27 PM
CSADNT wrote:
May be stupid question but is your service class public ?
Not a stupid question, i actualy made that mistake first (haven't we all once :), and corrected it.
The service class is public...
Developer
Jun 25, 2013 at 12:40 PM
Yes, it's exactly how it works.

A small checklist:
  • Is the feature containing the dependency enabled
  • Is the dependency implementation residing directly inside the module - if it's in a separate assembly it won't be found, even if it implements IDependency
  • Is the service class public
  • Is the class correctly decorated with IDependency interface
Coordinator
Jun 26, 2013 at 2:45 AM
Apparently nobody asked this: did you declare one module as a dependency of the other in the manifest file? This is important because it determines the order in which dependencies are processed by Autofac.
Developer
Jun 26, 2013 at 3:01 AM
Edited Jun 26, 2013 at 3:08 AM
The main module has a dependency to the service module in the Module.txt
So it looks like it is declared, but shouldn't it be the other way around or is it a typo? Because it's later written:
The interfaces for the service remains in the main module.
The service module has a reference (.net) to the main module (for the interfaces, modals,etc).
The module containing the implementation should be dependent on the one that contains the interface (both in the manifest and in .NET references).
Coordinator
Jun 26, 2013 at 3:19 AM
Ah yes, sorry I missed that.
Jun 26, 2013 at 7:33 AM
pszmyd wrote:
Yes, it's exactly how it works.

A small checklist:
  • Is the feature containing the dependency enabled
  • Is the dependency implementation residing directly inside the module - if it's in a separate assembly it won't be found, even if it implements IDependency
  • Is the service class public
  • Is the class correctly decorated with IDependency interface
Is the feature containing the dependency enabled ✔
Is the dependency implementation residing directly inside the module - if it's in a separate assembly it won't be found, even if it implements IDependency ??
Is the service class public ✔
Is the class correctly decorated with IDependency interface ✔
  • Is the dependency implementation residing directly inside the module - if it's in a separate assembly it won't be found, even if it implements IDependency
Not sure what you mean here. Isn'the whole idea of a module that it resides in a separate project with its own Module.txt, And therefor a separate assembly?
Or do you mean that the service module contains a reference to another (third) assembly?

Not a third assembly, but it does have a reference back to the main assembly.
The reason for this is that my model and service interfaces are in the main module.
Might this be the problem?
Jun 26, 2013 at 7:45 AM
Edited Jun 26, 2013 at 7:55 AM
pszmyd wrote:
The main module has a dependency to the service module in the Module.txt
So it looks like it is declared, but shouldn't it be the other way around or is it a typo? Because it's later written:
The interfaces for the service remains in the main module.
The service module has a reference (.net) to the main module (for the interfaces, modals,etc).
The module containing the implementation should be dependent on the one that contains the interface (both in the manifest and in .NET references).
Maybe i should explain what i am trying to do first.

Our main module must retrieve data from our existing webservices.
Theres an "old" one and a "new"one.
They both have different interfaces (the old one is an oldscool xml webservice, the new one is a WCF webservice)
Some of our customers use the old one, and some the new.

So i want to create 2 services with exacly the same interface, but with different "internal engines" (encapsulation)

If a customer uses the "old" webservice, we enable that module.
If the customer uses the "new" WCF webservice we enable that one.

I figured that modules and dependency injection are ideal for this scenario?
Developer
Jun 27, 2013 at 5:07 AM
Edited Jun 27, 2013 at 5:08 AM
Or do you mean that the service module contains a reference to another (third) assembly?
Meant exactly this - a third assembly. Those are not scanned when dependency auto-registration takes place.
So i want to create 2 services with exacly the same interface, but with different "internal engines" (encapsulation)
If a customer uses the "old" webservice, we enable that module.
If the customer uses the "new" WCF webservice we enable that one.
I figured that modules and dependency injection are ideal for this scenario?
Thanks, everything got way clearer now. You could do perfectly well using just a single module, but with two additional features (one for holding old and one for holding new implementation). Take a look at existing module manifests for examples of declaring multiple features inside a module.

How to code it? In short - put both implementations inside one module project (along with the interface), but decorate each with OrchardFeature attribute to tell Orchard to which feature (old or new one) they belong. Now, if you go to the admin screen and enable old or new, the correct implementation will get picked up. If OrchardFeature attribute is present, Orchard will register the implementation only if the given feature is enabled.
Same effect, but with just one module.
Jun 27, 2013 at 8:22 AM
Edited Jun 27, 2013 at 8:25 AM
pszmyd wrote:
...
Thanks, everything got way clearer now. You could do perfectly well using just a single module, but with two additional features (one for holding old and one for holding new implementation). Take a look at existing module manifests for examples of declaring multiple features inside a module.
...
Thanks, that works perfectly.

For others who read this, you also need to add the feature to the manifest (module.txt) file. http://docs.orchardproject.net/Documentation/manifest-files

Stil confused do why this did not work when te services where in a seperate module/project.
That should be possible right?

Anyway, thanks all for taking the time te respond.
Now where can i close this thread and mark pszmyd's answer as the solution? :)
Developer
Jun 27, 2013 at 2:37 PM
Maybe Codeplex will add such feature sometime:)

Yes, it should work ok and it actually does - there are lots of examples in the core code when an interface resides in one module and implementations in multiple others. What I think happened here was some problem with that backreference you had (if I understood correctly).

If you would have, let's say, Module A that contains an interface and Module B and Module C that contain two different implementations, both B and C projects should have a reference to A as well as dependency set in the manifest files. If you'd backreference either B or C from A weird things may happen (not to mention the circular reference).