Get an Instance using Ninject - c#

How can I get a single instance using Ninject? Here's my Service Module:
public class ServicesModule : NinjectModule
{
public override void Load()
{
Kernel.Bind<IDocumentServiceApi>().To<DocumentServiceApi>().InRequestScope();
Kernel.Bind<IConfigurationService>().To<ConfigurationService>().InRequestScope();
Kernel.Bind<IReportGenerationProcessor>().To<ReportGenerationProcessor>().InRequestScope();
}
}
I need an instance of IReportGenerationProcessor to fire off a message I am receiving from an Azure Service Bus Queue.
I've seen a lot of different ways, but none have worked for me. I constantly get the error :Object instance not set to an instance of an object.
//I do instantiate this class using new WebJobBase();
public class WebJobBase
{
public void ProcessMessage(BrokeredMessage message)
{
// Just need an instance of IReportGenerationProcessor here
var _processor = new ReportGenerationProcessor();
_processor.ProcessMessage(message);
}
}
Here's my IReportGenerationProcessor implementation:
public interface IReportGenerationProcessor
{
DocumentMetaData ProcessMessage(BrokeredMessage message);
}
public class ReportGenerationProcessor : IReportGenerationProcessor
{
// Go figure these don't work either
[Inject]
public IConfigurationService _config { get; set; }
[Inject]
public IDocumentServiceApi _docService { get; set; }
public DocumentMetaData ProcessMessage(BrokeredMessage message)
{
var report = message.GetBody<ReportMetaData>();
//Do some stuff
return new DocumentMetaData(); // just a place holder
}
}
If I can provide more information, please let me know. I'm not too knowledgeable on Ninject.

Okay, so the documentation kind of hinted at this, but they didn't use an Interface and registered .ToSelf().
Basically I needed to instantiate a new StandardKernel with my ServicesModule from above, and call the .Get<>(); method for my registered Interface.
IKernel kernel = new StandardKernel(new ServicesModule());
var processor = kernel.Get<IReportGenerationProcessor>();
processor.ProcessMessage(message);

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; }
}

Adding singlton for every browser tab

I'm trying to implement web application and using a singleton object so I would be able to inject it to use it in other classes.
I want to open a new object every time the user opens a tab or similar in the browser. For example:
public class Singleton
{
public string Id{get;set;}
public Singleton(){Id=Guid.NewGuid().ToString();)
}
in startup:
services.AddSingleton<Singleton>(s=>new Singleton());
In some other class:
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(Singleton singleton)
{
this.singleton = singleton;
}
}
The problem is that every tab has the same Id... I need a different id for every tab in the browser...
Thanks!
You have to make an Interface for the class you want to be a singleton. You register it in your Startup.cs as a Singleton
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISingleton, Singleton>();
}
You then proceed to inject the singleton interface into OtherClass
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(ISingleton singleton)
{
this.singleton = singleton;
}
Hope this helps
Ok I've found some solution....
I'm creating a singleton class that has an object that will change ...
When I want to change the object details, I do this in a method...
Then I have the updated information for all the WebApp.
The change will be made in every method that I need to specify the object details...
For example:
public class InjectedSingleton
{
public MySession CurrentSession{get;set;}
public void SetSession(string sessionId)
{
CurrentSession = GetSessionById(sessionId);
}
public void NewSession()
{
CurrentSession = new MySession();
}
}
public class DoClass
{
private InjectedSingleton inj;
public DoClass(InjectedSingleton inj)
{
this.inj = inj;
}
public void OpenNewTab(string sessionId)
{
inj.SetSession(sessionId);
}
public void JustShowSomething()
{
Show(inj.CurrentSession.Id);
}
}
Now, the updated session is the required one, for everywhere in the app for the current user

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?

Ninject - Bind different interfaces implementations to the same class

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.

How can one use an existing instance to select a type to create in an IoC container

this is probably just a newbie question, but I have the following:
public class FooSettings {}
public class BarSettings {}
public class DohSettings {}
// There might be many more settings types...
public interface IProcessor { ... }
public class FooProcessor
: IProcessor
{
public FooProcessor(FooSettings) { ... }
}
public class BarProcessor
: IProcessor
{
public BarProcessor(BarSettings) { ... }
}
public class DohProcessor
: IProcessor
{
public DohProcessor(DohSettings) { ... }
}
// There might be many more processor types with matching settings...
public interface IProcessorConsumer {}
public class ProcessorConsumer
: IProcessorConsumer
{
public ProcessorConsumer(IProcessor processor) { ... }
}
An instance of either FooSettings or BarSettings is provided from an external source i.e.:
object settings = GetSettings();
And now I would like to resolve ProcessorConsumer based on injecting the existing instance of settings e.g.:
container.RegisterAssemblyTypes(...); // Or similar
container.Inject(settings);
var consumer = container.Resolve<IProcessorConsumer>();
That is if an instance of FooSettings is provided then a FooProcessor is created and injected into the ProcessorConsumer which is then the instance resolved.
I haven't been able to figure out how to do this in either StructureMap, Ninject nor Autofac... probably because I am a newbie when it comes to IoC containers. So answers for all of these or other containers so they can be compared would be highly appreciated.
UPDATE: I am looking for a solution which easily allows for new settings and processors to be added. Also there will be a one-to-on mapping from settings type to processor type. But which also allows for other instances/services to be injected in a given processor type, based on its constructor parameters. I.e. some processor might need a IResourceProvider service or similar. Just an example here.
Ideally, I would like something like
container.For<IProcessor>.InjectConstructorParameter(settings)
or similar. Thereby, guiding the IoC container to use the processor type matching the injected constructor parameter instance.
You don't want dependency injection for this. You want a factory (which, of course, you can build using your container). The factory would know how to take, say, an IProcessorSettings and return the appropriate IProcessor. In short, you can build a factory that uses the concrete type of an object that implements IProcessorSettings and the container to resolve an instance of the appropriate type.
I think what you are looking for is the ForObject() method in StructureMap. It can close an open generic type based on a given object instance. The key change you need to make to your design is to introduce the generic type:
public interface IProcessor { }
public interface IProcessor<TSettings> : IProcessor{}
All of the important stuff is still declared on IProcessor, the generic IProcessor<TSettings> is really just a marker interface. Each of your processors will then implement the generic interface, to declare which settings type they expect:
public class FooProcessor : IProcessor<FooSettings>
{
public FooProcessor(FooSettings settings) { }
}
public class BarProcessor : IProcessor<BarSettings>
{
public BarProcessor(BarSettings settings) { }
}
public class DohProcessor : IProcessor<DohSettings>
{
public DohProcessor(DohSettings settings) { }
}
Now, given an instance of a settings object, you can retrieve the correct IProcessor:
IProcessor processor = container.ForObject(settings).
GetClosedTypeOf(typeof(IProcessor<>)).
As<IProcessor>();
Now you can tell StructureMap to use this logic whenever it resolves an IProcessor:
var container = new Container(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.ConnectImplementationsToTypesClosing(typeof(IProcessor<>));
});
x.For<IProcessor>().Use(context =>
{
// Get the settings object somehow - I'll assume an ISettingsSource
var settings = context.GetInstance<ISettingsSource>().GetSettings();
// Need access to full container, since context interface does not expose ForObject
var me = context.GetInstance<IContainer>();
// Get the correct IProcessor based on the settings object
return me.ForObject(settings).
GetClosedTypeOf(typeof (IProcessor<>)).
As<IProcessor>();
});
});
StructureMap containers expose the Model property which allows you to query for the instances it contains.
var container = new Container(x =>
{
x.For<IProcessorConsumer>().Use<ProcessorConsumer>();
x.For<IProcessor>().Use(context =>
{
var model = context.GetInstance<IContainer>().Model;
if (model.PluginTypes.Any(t => typeof(FooSettings).Equals(t.PluginType)))
{
return context.GetInstance<FooProcessor>();
}
return context.GetInstance<BarProcessor>();
});
});
In Autofac given:
public class AcceptsTypeConstructorFinder
: IConstructorFinder
{
private readonly Type m_typeToAccept;
public AcceptsTypeConstructorFinder(Type typeToAccept)
{
if (typeToAccept == null) { throw new ArgumentNullException("typeToAccept"); }
m_typeToAccept = typeToAccept;
}
public IEnumerable<ConstructorInfo> FindConstructors(Type targetType)
{
return targetType.GetConstructors()
.Where(constructorInfo => constructorInfo.GetParameters()
.Select(parameterInfo => parameterInfo.ParameterType)
.Contains(m_typeToAccept));
}
}
the following works:
// Load
var settings = new BarSettings();
var expectedProcessorType = typeof(BarProcessor);
// Register
var constructorFinder = new AcceptsTypeConstructorFinder(settings.GetType());
var builder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
builder.RegisterInstance(settings);
builder.RegisterAssemblyTypes(assembly)
.Where(type => type.IsAssignableTo<IProcessor>() && constructorFinder.FindConstructors(type).Any())
.As<IProcessor>();
builder.RegisterAssemblyTypes(assembly)
.As<IProcessorConsumer>();
using (var container = builder.Build())
{
// Resolve
var processorConsumer = container.Resolve<IProcessorConsumer>();
Assert.IsInstanceOfType(processorConsumer, typeof(ProcessorConsumer));
Assert.IsInstanceOfType(processorConsumer.Processor, expectedProcessorType);
// Run
// TODO
}
However, I find this to be rather cumbersome and was hoping for something more built into an IoC container.
Now, I'm not saying this is the right way to do this. However, it may be another option if you are using Autofac. This assumes that you are happy for the registration delegate to call GetSettings at the point you try and resolve the IProcessorConsumer. If you are able to do that, you can do what you want in the registration, as below:
var cb = new ConatainerBuilder();
cb.Register(c =>
{
var settings = GetSettings();
if(settings is FooSettings)
return new FooProcessor((FooSettings)settings);
else if(settings is BarSettings)
return new BarProcessor((BarSettings)settings);
else
throw new NotImplementedException("Hmmm. Got some new fangled settings.");
}).As<IProcessor>();
//Also need to register IProcessorConsumer
Note: This code may be wrong as I can't try it right now.
Here is as close as you can get to a proper factory method. But there are some issues. First, here's the code; then we'll talk.
public class FooSettings
{
public int FooNumber { get; set; }
public string FooString { get; set; }
}
public class BarSettings
{
public int BarNumber { get; set; }
public string BarString { get; set; }
}
public interface IProcessor
{
void Process();
}
public class FooProcessor : IProcessor
{
public FooProcessor(FooSettings settings) { }
public void Process() { }
}
public class BarProcessor : IProcessor
{
public BarProcessor(BarSettings settings) { }
public void Process() { }
}
public interface IProcessorFactory
{
IProcessor GetProcessor(object settings);
}
public interface IProcessorConsumer { }
public class ProcessorConsumer : IProcessorConsumer
{
private IProcessorFactory _processorFactory;
private object _settings;
public ProcessorConsumer(IProcessorFactory processorFactory, object settings)
{
_processorFactory = processorFactory;
_settings = settings;
}
public void MyLogic()
{
IProcessor processor = _processorFactory.GetProcessor(_settings);
processor.Process();
}
}
public class ExampleProcessorFactory : IProcessorFactory
{
public IProcessor GetProcessor(object settings)
{
IProcessor p = null;
if (settings is BarSettings)
{
p = new BarProcessor(settings as BarSettings);
}
else if (settings is FooSettings)
{
p = new FooProcessor(settings as FooSettings);
}
return p;
}
}
So what's the issue? It's the different types of settings that you're giving to your factory method. Sometimes it's FooSettings and sometimes it's BarSettings. Later, it might be xxxSettings. Each new type will force a recompilation. If you had a common Settings class, this would not be the case.
The other issue? Your consumer gets passed the factory and the settings and uses that to get the correct processor. If you have someone passing these to your consumer, just have that entity call GetProcessor on the Factory and pass the resulting IProcessor to the consumer.
I think the issue is that you haven't actually specified in any structured way how to resolve a processor from a settings instance. How about making the settings object return the processor? That seems to be the right place to put this information:
public interface ISettings
{
IProcessor GetProcessor();
}
Each implementation must resolve its own processor implementation:
public class FooSettings : ISettings
{
//this is where you are linking the settings type to its processor type
public IProcessor GetProcessor() { return new FooProcessor(this); }
}
And any code needing a processor gets it from the settings object, which you can reference from the consumer constructor:
var consumer = new ProcessorConsumer(Settings.GetProcessor());

Categories

Resources