Ninject - Bind different interfaces implementations to the same class - c#

I'm new to DI (using Ninject) and just started to learn the concepts, but I've been scratching my head for a while to understand this:
Suppose I have DIFFERENT usage of the same class in my program (ProcessContext in the example below).
In the first class (SomeClass) : I would like to inject Implement1 to ProcessContext instance.
In the second class (SomeOtherClass) : I would like to inject Implement2 to ProcessContext instance.
How should I perform the bindings using Ninject ?
public class Implement1 : IAmInterace
{
public void Method()
{
}
}
public class Implement2 : IAmInterace
{
public void Method()
{
}
}
public class ProcessContext : IProcessContext
{
IAmInterface iamInterface;
public ProcessContext(IAmInterface iamInterface)
{
this.iamInterface = iamInterface;
}
}
public class SomeClass : ISomeClass
{
public void SomeMethod()
{
// HERE I WANT TO USE: processcontext instance with Implement1
IProcessContext pc = kernel.Get<IProcessContext>();
}
}
public class SomeOtherClass : ISomeOtherClass
{
public void SomeMethod()
{
// HERE I WANT TO USE: processcontext instance with Implement2
IProcessContext pc = kernel.Get<IProcessContext>();
}
}

You could use named bindings for this.
e.g. something like:
Bind<IProcessContext>()
.To<ProcessContext>()
.WithConstructorArgument("iamInterface", context => Kernel.Get<Implement1>())
.Named("Imp1");
Bind<IProcessContext>()
.To<ProcessContext>()
.WithConstructorArgument("iamInterface", context => Kernel.Get<Implement2>())
.Named("Imp2");
kernel.Get<IProcessContext>("Imp1");

You can inject additional constructor parameters easily in this way:
public void SomeMethod()
{
var foo = new Ninject.Parameters.ConstructorArgument("iamInterface", new Implement2());
IProcessContext pc = kernel.Get<IProcessContext>(foo);
}
For now, I don't have access to ninject. So tell me if it doesn't work as expected.

This is not possible as Ninject has no way of knowing which implementation to return. However; if you create a new instance of your IProcessContext by passing in a variable then Ninject will look for the implementation with the appropriate constructor and return that one.

Related

Having some parameters Injected with DI and some assigned manually

In a .NET Core 3.1 console application I want a Class that would have some parameters in constructor injected but some that I could assign manually. For example something like that but with IConfiguration Injected:
static void Main() {
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
}
public class MyClass {
public MyClass(IConfiguraiton config, int myVal)
{
}
}
I tried this with Ninject:
static void Main()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
}
public class MyClass
{
public MyClass(IConfiguraiton config)
{
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
}
}
I managed to make simple dependency injection, but haven't had any success making injection with parameters.
I've read a lot of people suggesting that it's better to pass parameters into methods of the class rather than constructor, however in my situation this isn't an option in addition I'm a software engineering student, and would like to learn how to do this, since it might be useful in some situations.
This is a situation where the Ninject.Extensions.Factory is useful, as it is made exactly for this situation. It does pull in the Factory dependency in addition to Castle.Core, as it uses DynamicProxy under the hood (as a SE student, playing with this library is a good idea for using the interceptor pattern).
To use it, you define a Factory interface like so:
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
Note that the Create method returns MyClass, and the argument(s) to the Create method match exactly in type and name to the arguments you wish to provide. The argument type(s) you want injected must be registered with the kernel. Unfortunately, it is easy to make a mistake here - if you specify a parameter that does not exist in the factory interface it is ignored, but if you forget one it will throw an exception when called.
Next, register IMyClassFactory like this: Bind<IMyClassFactory>().ToFactory(); and remove your binding for MyClass. Then wherever you need to create an instance, inject IMyClassFactory and call Create: kernel.Get<IMyClassFactory>().Create(2)
You can achieve the same result without using Ninject.Extensions.Factory by writing and registering your own implementation of IMyClassFactory, essentially doing the same thing that the code the Factory extension ends up emitting. A full sample is below using both methods based on commenting in/out the registration (note the output if you add .InSingletonScope() to the registration of IConfiguraiton - both approaches respect the binding scopes of Ninject).
internal class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
}
}
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
public class NinjectMyClassFactory : IMyClassFactory
{
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
{
ResolutionRoot = resolutionRoot;
}
private IResolutionRoot ResolutionRoot { get; }
public MyClass Create(int myVal)
{
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
}
}
public class MyClass
{
public MyClass(IConfiguraiton config, int myVal)
{
Console.Out.WriteLine("Created MyClass({0},{1})", config.MyNum, myVal);
}
}
public interface IConfiguraiton { int MyNum { get; } }
public class Configuraiton : IConfiguraiton
{
static int CreateCount;
public Configuraiton()
{
MyNum = Interlocked.Increment(ref CreateCount);
}
public int MyNum { get; }
}

Handling two different application flows

We are building an application where we have to have both old and new version to work side by side (V1 is old and V2 is new). Now to handle new flow we are using same old interfaces with everything being the same and differs only in functionality, hence now we have to define a named instance in-order to resolve the instances for new flow.
In the process teams have started using Service Factory Pattern as shown below
class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IServiceFactory serviceFactory)
{
_dataManager = serviceFactory.GetInstance<IDataManager>();
}
public void Execute()
{
_dataManager.Run();
}
}
Service Factory Class
public class ServiceFactory : IServiceFactory
{
private readonly IFeatureEvaluator _featureEvaluator;
public ServiceFactory(IFeatureEvaluator featureEvaluator)
{
_featureEvaluator = featureEvaluator;
}
public T GetInstance<T>()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
return ObjectFactory.GetInstance<T>("V2")
}
return ObjectFactory.GetInstance<T>();
}
}
Since Service Factory is anti-pattern and also it creates lot of complexities in retiring the old flow in future, I would want a way to initialize the dependencies at the container(structuremap ioc) itself or to work in a "Pure DI" way so that we can avoid headache. Any idea on how to tackle this.
Update:
IDataManager Implementation
public interface IDataManager
{
void Run();
}
public class OldFlow : IDataManager
{
public void Run()
{
//
}
}
public class NewFlow : IDataManager
{
public void Run()
{
//
}
}
IDataManager has 2 implementations and resolving the instance should be based on _featureEvaluator, if V2 flow then "newflow" should be instantiated else "old flow" instance
Why don't you just inject the dependency you need?
public class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IDataManager dataManager)
{
_dataManager = dataManager;
}
public void Execute()
{
_dataManager.Run();
}
}
In your Composition Root you can conditionally compose DataProcessor with the implementation of IDataManager you'd like:
public DataProcessor CreateDataProcessor()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
IDataManager dm = new NewFlow();
return new DataProcessor(dm);
}
IDataManager dm = new OldFlow();
return new DataProcessor(dm);
}
This seems to be similar to feature toggles. Why, by the way, is _featureEvaluator an interface? Wouldn't a bool suffice?

Generic Interface dependency injection into factory

I'm playing around with DI and Ninject. I'm open for suggestions on how to solve this in another way. I'm trying to make sure the concrete implementations of ICreateOrders can be replaced - if need be. Maybe there's another way or pattern?
Solutions like this: C# - Ninject, IoC and factory pattern are fine but I was hoping to inject the possible creators into the factory and making the factory pick one based on OrderRequest.
This doesn't work.
kernel.Bind(typeof(ICreateOrders<,>)).To(typeof(OrderCreator))
I can kind of understand why not. But even another signature of OrderCreator to OrderCreator<,> or actually providing the Interfaces and/or concrete classes to the generic parameters don't work and ideally, I don't want to do that because the implementor of a new OrderCreator should just do something like this
public class HorseOrderCreator : ICreateOrders<HorseOrderRequest, HorseOrderResponse>
{
public HorseOrderResponse Create()
{
throw new NotImplementedException();
}
}
Sample code
using System;
using Ninject;
using System.Collections.Generic;
using System.Linq;
namespace NinjectPlatyGround
{
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind(typeof(ICreateOrders<,>)).To(typeof(OrderCreator));
kernel.Bind<IOrderCreatorFactory>().To<OrderCreatorFactory>();
var factory = kernel.Get<IOrderCreatorFactory>();
var orderCreator = factory.GetOrderCreator(new OrderRequest());
}
}
public class OrderRequest : IOrderRequest
{
}
public class OrderResponse : IOrderResponse
{
}
public class OrderCreator : ICreateOrders<OrderRequest, OrderResponse>
{
public OrderResponse Create()
{
throw new NotImplementedException();
}
}
public class OrderCreatorFactory : IOrderCreatorFactory
{
private readonly IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders;
public OrderCreatorFactory(IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders)
{
this.createOrders = createOrders;
}
public ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest)
{
//Based on orderRequest i find the implementation i need.
return this.createOrders.First();
}
}
public interface ICreateOrders<TOrderRequest, TOrderResponse> where TOrderRequest : IOrderRequest where TOrderResponse : IOrderResponse
{
TOrderResponse Create();
}
public interface IOrderCreatorFactory
{
ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest);
}
public interface IOrderRequest
{
}
public interface IOrderResponse
{
}
}
I'm aware that I need to inject multiple concrete instances of ICreatorOrders to make Ninject give me an IEnumerable in the factory. Just pointing out with the code what I'm actually trying to do.
As suggested in the comments, you may try to specify ICreateOrders as
ICreateOrders<out TOrderRequest, out TOrderResponse>
You should then be able to write and to resolve successfully :
kernel.Bind(typeof(ICreateOrders<,>)).To(typeof(OrderCreator))

How to access classes with on one instance?

I have multiple classes in the service layer of my app.
Let's say I need to access some method from AbcService.cs in my controller. Then, I need to access some method from XyzService.cs in the same controller. Then another.......For this, I would need to create an object of each Service class separately in the constructor. Also, if I needed to access these methods in another cntroller I would again have to create objects of AbcService, XyzService, etc. I want to have one instance that can give me access to methods of all service classes.
Something like:
generalService.AbcService.MethodName();
generalService.AbcService.MethodName();
How do I do this in the best possible way?
You can use inheritance and create a class that (eventually) inherits from all of them, thus inheriting their methods. Or you can make them inherit from each other (this way you'll have to use the service class that inherits from both, as it would have all the methods that can be inherited).
To put it very simply, it can go like this using inheritance (I assume the service classes were not inheriting from anything until now):
public class ServiceClassA
{
//Certain Methods
}
public class ServiceClassB : ServiceClassA
{
//Other methods, this class also has ServiceClassA methods
}
public class ServiceClassC : ServiceClassB
{
//Even more methods, this class also has ServiceClassA and ServiceClassB methods
}
//... and so on
Assuming the lowest class in the inheritance tree is ServiceClassC for example, you only need a ServiceClassC object and you'll be able to access the needed (inherited) methods.
Create service layer so that other componentns can access easily.
public class Program
{
static void Main(string[] args)
{
Global.ServiceABC.MethodA();
Global.ServiceXYZ.MethodB();
}
}
public class Global
{
private static ABC serviceABC;
public static ABC ServiceABC { get
{
if (serviceABC == null)
{
serviceABC = new ABC();
}
return serviceABC;
}
}
private static XYZ serviceXYZ;
public static XYZ ServiceXYZ
{
get
{
if (serviceXYZ == null)
{
serviceXYZ = new XYZ();
}
return serviceXYZ;
}
}
}
public class ABC
{
public void MethodA() { }
}
public class XYZ
{
public void MethodB() { }
}
Unfortunately in C# you can NOT inherit from two classes at once so something like
public class CombinedService : AbcService, XyzService {
}
is not possible.
You can however use static methods to have only one instance per service like this:
public static class ServiceManager {
// The variable holding the instance
private static AbcService _abcService = null;
// Access to the instance and single instance creator
public static AbcService AbcServiceInstance {
get {
if (_abcService == null) {
// Create your Instance here
_abcService = new AbcService();
}
return _abcService;
}
}
// The variable holding the instance
private static XyzService _xyzService = null;
// Access to the instance and single instance creator
public static XyzService XyzServiceInstance {
get {
if (_xyzService == null) {
// Create your Instance here
_xyzService = new XyzService();
}
return _xyzService;
}
}
}
Because they are static you can access them from everywhere in the code just by calling the static class properties like this:
ServiceManager.AbcServiceInstance.SomeMethod();
ServiceManager.XyzServiceInstance.SomeMethod();
You can also shorten the instantiation and accessor like this:
private static AbcService _abcService = new AbcService();
public static XyzService XyzServiceInstance {
get { return _abcService; }
}
If the instances can just be created like this and don't need any more parameters or configuration.
You should consider using a dependency injection container like Autofac. Register your service classes as Single Instance scope. You will get only one instance of a service class whenever you request it in every individual controller and even you do not need to create instance of it on your own.All is done by Ioc Container.
var builder = new ContainerBuilder();
builder.RegisterType<SomeService>().SingleInstance();
It somewhat depends how you choose to implement your services, but generally speaking you want some layer that encapsulate your services which is a singleton or that you inject\produce a single instance of it.
Encapsulation:
First try to look at a facade design pattern.
http://www.dofactory.com/net/facade-design-pattern
And btw if you don't need something complex and don't mind have an extra level of indirection then you can have some version of the facade like
KindOfSimpleFacade
{
public IServiceA ServiceA { get; }
public IServiceB ServiceB { get; }
}
Regarding the singleton there are a few ways to get it:
inject the facade object to the (just provide the same instance to each one of the controllers as an input).
(Facade) Factory -http://tutorialspoint.com/design_pattern/factory_pattern.htm
The factory will produce a single instance of the facade.
use static members inside the facade for example:
public class KindOfSimpleFacade
{
private static readonly serviceA = new ServiceA();
private static readonly serviceB = new ServiceB();
public IServiceA ServiceA { get { return serviceA; } }
public IServiceB ServiceB { get { return serviceB; } }
}

Configuring an Autofac delegate factory that's defined on an abstract class

I'm working on a C# project. I'm trying to get rid of a Factory class that has a large switch statement.
I want to configure Autofac to be able to construct a dependency based on a parameter, thereby allowing Autofac to take the place of the Factory.
I've looked at the DelegateFactories page of the Autofac wiki, but I can't figure out how to apply the pattern to an abstract class. Here's some code showing the situation:
public enum WidgetType
{
Sprocket,
Whizbang
}
public class SprocketWidget : Widget
{
}
public class WhizbangWidget : Widget
{
}
public abstract class Widget
{
public delegate Widget Factory(WidgetType widgetType);
}
public class WidgetWrangler
{
public Widget Widget { get; private set; }
public WidgetWrangler(IComponentContext context, WidgetType widgetType)
{
var widgetFactory = context.Resolve<Widget.Factory>();
Widget = widgetFactory(widgetType);
}
}
I'd like it if I were to say new WidgetWrangler(context, WidgetType.Sprocket), its Widget property would be a SpocketWidget.
When I try this, I get errors stating that Widget.Factory is not registered. Does this delegate factory pattern not work with abstract classes, and if so, is there another way to accomplish this?
What you're looking for is the IIndex<,> Relationship Type.
If you register your sub-classes with .Keyed<>(...) you can key a registration to a value (object).
For example:
builder.RegisterType<SprocketWidget>()
.Keyed<Widget>(WidgetType.Sproket)
.InstancePerDependency();
builder.RegisterType<WhizbangWidget>()
.Keyed<Widget>(WidgetType.Whizbang)
.InstancePerDependency();
Then you only require a dependency of IIndex<WidgetType,Widget> to mimic factory behaviour.
public class SomethingThatUsesWidgets
{
private readonly IIndex<WidgetType,Widget> _widgetFactory;
public SomethingThatUsesWidgets(IIndex<WidgetType,Widget> widgetFactory)
{
if (widgetFactory == null) throw ArgumentNullException("widgetFactory");
_widgetFactory = widgetFactory;
}
public void DoSomething()
{
// Simple usage:
Widget widget = widgetFactory[WidgetType.Whizbang];
// Safe Usage:
Widget widget2 = null;
if(widgetFactory.TryGetValue(WidgetType.Sprocket, out widget2))
{
// do stuff
}
}
}
That's using Dependency Injection approach, if you just want to resolve the factory:
var factory = Container.Resolve<IIndex<WidgetType,Widget>>();

Categories

Resources