Ozkan
Ozkan

Reputation: 4170

Constructor injected implementation has a dll dependency which is not used

As you know, Ninject binds all interfaces to implementations in the composition root. We have a class which is dependent on an external dll, but we don't want to deploy it (the physical dll file in the bin directory) if it's not being used. The class ExampleClass is stored in our Framework project, this means it's referenced by any application we are building. And that's why we are getting the following when deploying any of our application:

Could not load file or assembly ExternalDll, Version=x.x.x.xxx, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx

Is there any workaround, like encapsulating the implementation into another class or something? Or runtime initialisation (Factory pattern). Which of these will solve my problem? I also tried Lazy binding but without success.

Constructor injection of implementation where the external dll is being used

namespace Framework
{
    public class ExampleClass
    {
        private readonly IUsesExternalDll _usesExternalDll;

        public ExampleClass(IUsesExternalDll usesExternalDll)
        {
            _usesExternalDll = usesExternalDll;
        }
    }
}

Interface

public interface IUsesExternalDll
{

}

Implementation

using externalDll; //this using is a reference to external dll

public class UsesExternalDll : IUsesExternalDll
{

}

Binding

kernel.Bind<IUsesExternalDll>().To<UsesExternalDll>().InTransientScope();

Upvotes: 3

Views: 243

Answers (2)

Ozkan
Ozkan

Reputation: 4170

How I solved this:

1) Move the Ninject binding to the specific application where it is used (higher level).

2) Make the constructor injected parameter Optional.

namespace Framework
{
    public class ExampleClass
    {
        private readonly IUsesExternalDll _usesExternalDll;

        public ExampleClass([Optional] IUsesExternalDll usesExternalDll)
        {
            _usesExternalDll = usesExternalDll;
        }
    }
}

Optional Attribute will lead to only being instantiated if there is a binding. And since I moved the bindings to the specific application where it is being used, in all other applications I won't get the Could not load file or assembly error because UsesExternalDll is not instantiated.

Upvotes: 0

Jan Muncinsky
Jan Muncinsky

Reputation: 4408

You can replace your binding with convention binding:

kernel.Bind(x => x.FromAssembliesMatching("AssemblyWhereUsesExternalDllIsLocated.dll")
    .SelectAllClasses()
    .BindAllInterfaces()
    .Configure(c => c.InTransientScope()));

Now types inside are bound only when this assembly is found.

Upvotes: 0

Related Questions