Reputation: 4170
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
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
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