I have such a class
public sealed class SimpleTextIndex<T> : TextIndex where T : ITextParser
{
[Inject]
public T TextParser { get; set; }
// something...
And dependency resolving method
public void Resolve()
{
Kernel = new StandardKernel();
Kernel.Bind(typeof(ITextParser)).To(typeof(WordTextParser));
Kernel.Bind(typeof(SimpleTextIndex<>)).ToSelf();
}
WordTextParser is a class, which implements ITextParser interface.
But, after calling Resolve() method and kernel's Get() method:
var textIndex = kernel.Get<SimpleTextIndex<ITextParser>>();
I'm getting a NullReferenceException (TextParser property in SimpleTextIndex is null)!
But, if I write a default constructor for SimpleTextIndex this way:
public SimpleTextIndex()
{
DependencyResolver.Kernel.Inject(this);
}
Everything works fine! Why?
The problem is that property injection is done only after the object is constructed via the constructor, i.e., Ninject cannot set the property value before the constructor is done.
Since you are using the dependency from a method invoked from the constructor, then the property is not yet set and therefore its value is null.
Either don't use the dependency during construction or use Constructor Injection like this:
//[Inject] //remove this attribute
public T TextParser { get; set; }
public SimpleTextIndex(T parser, string text = "")
{
TextParser = parser;
...
}
Related
I have a class named SomeRule that can be serialized in a XML format. The class uses an ISomeService that I would like to be injected via autofac.
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
private readonly ISomeService m_someService;
private SomeRule() { }
public SomeRule(ISomeService someService)
{
m_someService = someService;
}
public void DoSomething()
{
m_someService.DoStuff(Attribute1);
}
}
public interface ISomeService {
void DoStuff(string param);
}
public class SomeServiceImpl : ISomeService
{
public void DoStuff(string param) => // Do something with the stuff.
}
Now, my program receives an XML string that I would like to deserialize but also, at the same time, have autofac inject the dependency for me.
void Main()
{
string serializedRule =
"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
"<SomeRule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"Attribute1=\"Huuuuuge\" " +
"Attribute2=\"Cofveve\" />";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SomeRule));
var stringBuilder = new StringBuilder(serializedRule);
var newRule = xmlSerializer.Deserialize(
new StringReader(stringBuilder.ToString())) as SomeRule;
// ISomeService was not injected yet. Is it possible?
}
I can make this work by calling the autofac container, get the registered implementation of the ISomeService interface and assign it to a public property of the SomeRule instance. I am looking for a better solution, one that would not require the class to have a public property.
Is there a way to automatically inject dependencies with XmlSerializer?
From a DI standpoint, having data-centric objects with constructors that accepts service dependencies is rather problematic, and should be prevented.
When practicing DI, we try to centralize the composition of our object graphs of application components (i.e. the classes that contain behavior and have dependencies of their own) to a centralized place in the application called the Composition Root.
A data-centric object that includes constructor dependencies, however, complicates this practice, since it either forces composition out of the Composition Root, or forces the addition of factory abstractions for the creation of these objects.
Instead, you should use one of following two alternatives:
Separate data and behavior. This means moving SomeRule's DoSomething method to a new class, that takes SomeRule as an argument in its public method(s). The constructor dependency will move to this new class as well.
Remove the constructor dependency of SomeRule and instead inject it into DoSomething using method injection.
Option 1 might look like this:
// SomeRule only contains data. Much simpler
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
}
// Moved behavior to new class. This class can be injected
// into consumers, as usual.
public class SomeRuleHandler : IRuleHandler<SomeRule>
{
private readonly ISomeService m_service;
// There's now just one constructor left
public SomeRuleHandler(ISomeService service)
{
m_service = service ?? throw new ArgumentNullException("service");
}
public void DoSomething(SomeRule rule)
{
m_service.DoStuff(rule.Attribute1);
}
}
With option 2, the result will be the following:
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 { get; set; }
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
// No more constructors. The dependency is supplied in the method,
// but *not* stored.
public void DoSomething(ISomeService service)
{
service.DoStuff(Attribute1);
}
}
I'm trying to refactor some code to use IoC with the Ninject framework. So far I have managed to successfully inject in classes in scenarios where I do not have any constructor parameters to pass. However I am having difficulties when it comes to passing in parameters. This is the third binding in the binding class below.
Binding Class
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<Logger>();
Bind<IPlayerDatadao>().To<PlayerDatadao>();
Bind<IPlayerScores>().To<PlayerScores>();
}
}
The logger class has a parameterless constructor and works fine when transferred to Ninject.
Success
// IoC creation
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
//Log User details
var logger = kernel.Get<ILogger>();
logger.LogVisitorDetails();
However, my attempt below threw an exception
Failure
string priceString = Foo();
string pointsString = Bar();
return kernel.Get<IPlayerScores>(new[] { new ConstructorArgument("pointsString", pointsString), new ConstructorArgument("points", priceString) });
This is the class with its constructor.
Class to Inject
public class PlayerScores : IPlayerScores
{
[Inject]
public string points { get; set; }
[Inject]
public string price { get; set; }
public PlayerScores(string Points, string Price)
{
points = Points;
price = Price;
}
}
I'm really not sure how I should be handling the parameters either in the binding class or at the point of injection
I'm really not sure how I should be handling the parameters either in the binding class or at the point of injection
At binding. You should remove any Ninject dependencies from your model:
public class PlayerScores : IPlayerScores
{
public PlayerScores(string points, string price)
{
this.Points = points;
this.Price = price;
}
public string Points { get; set; }
public string Price { get; set; }
}
and then configure the kernel:
Bind<IPlayerScores>()
.To<PlayerScores>()
.WithConstructorArgument("points", "some points")
.WithConstructorArgument("price", "some price");
or using ToMethod which is a bit more refactor friendly as it avoids the magic strings with the parameter names:
Bind<IPlayerScores>()
.ToMethod(ctx => new PlayerScores("some points", "some price"));
This being said, if the 2 parameters are so volatile that they need to have a different value on each call, then you probably should not be passing them as constructor parameters but rather as parameters to some instance method that you would invoke on the class at runtime.
I have a controller which contains a business class that internally has dependencies to a datahandler. For testing that business class I need to mock the datahandler. After setup, I am assigning the business class' datahandler with the mocked datahandler. But while debugging, the business class' datahandler is showing null , I know that I should use the constructor to inject the mocked object.But is it possible to do it without using any constructor injection ?Can any body help me with this?
my business class:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
Test class:
public class FooBusinessTest
{
...
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x=>x.Search(It.IsAny<int>).Returns(1);
...
FooBusiness _fooBusiness = new FooBusiness();
FooBusiness._barDatahandler = _mockedBarDataHandler.Object;
//Act
...
}
}
As I mentioned, there are multiple ways to achieve your needs.
Personally I like Shyju's answer more (Constructor Injection), but if you can't change the constructor, you can still change the implementation afterwards by setting the property:
business class:
public class FooBusiness
{
private IBarDataHandler _barDatahandler = new BarDatahandler();
public IBarDataHandler BarDatahandler
{
get { return _barDatahandler; }
set { _barDatahandler = value; }
}
public int Search(int a)
{
return _barDatahandler.Search(a);
}
}
Test class:
public class FooBusinessTest
{
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x => x.Search(It.IsAny<int>).Returns(1);
FooBusiness fooBusiness = new FooBusiness();
fooBusiness.BarDatahandler = _mockedBarDataHandler.Object;
//Act
}
}
If you worry about to refactor the implementation, it is better to setup all the tests first. After that you can refactor with a safer feeling :)
You need to inject your dataHandler dependency to FooBusiness
You need to extract an interface for your BarDataHandler if one does not exist.
interface IBarDataHandler
{
string GetUserToken(int id);
}
public class BarDataHandler : IBarDataHandler
{
public string GetUserToken(int id)
{
// to do :read from db and return
}
}
And add a constructor to FooBusiness class which accepts an implementation of IBarDataHandler.
public class FooBusiness
{
IBarDataHandler barDataHandler;
public FooBusiness(IBarDataHandler barDataHandler)
{
this.barDataHandler=barDataHandler
}
public string GetUserToken(int id)
{
return this.barDataHandler.GetUserToken(id);
}
}
You can use any one of the dependency injection frameworks like Unity/Ninject/StructureMap to resolve your concrete implementation when your app runs.
You can use any mocking framework like Moq to mock the fake implementation of IBarDataHandler in your unittests.
Typically, to register some configuration value using constructor injection I would do this:
string setting = ConfigurationManager.AppSettings["SomeSetting"];
container.Register<IService>(new Service(setting));
How do you accomplish something similar, in order to pass a configuration value into a decorator constructor?
Is the only means to create some configuration provider class which could get injected into the decorator? Seems like RegisterDecorator should have an overload which allows manually newing the class as needed.
There are several ways to achieve this. If that part of the object graph is simple, building the object graph by hand might give the best results:
container.RegisterSingleton<IService>(new ServiceDecorator(
setting,
new RealService()));
// or
container.Register<IService>(() => new ServiceDecorator(
setting,
new RealService()));
There is no delegate overload for RegisterDecorator in Simple Injector, which means that you can't register a decorator using RegisterDecorator that is hand-wired, but there some alternative approaches.
You can extract the setting value into its own class. This allows the that abstraction to get injected into the decorator:
container.RegisterSingleton<MySetting>(new MySetting(setting));
container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));
public ServiceDecorator : IService {
public ServiceDecorator(MySetting setting, IService decoratee) { }
}
Or you can inject the setting into a property of the decorator:
container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));
container.RegisterInitializer<ServiceDecorator>(dec => dec.Setting = setting);
public ServiceDecorator : IService {
public string Setting { get; set; }
public ServiceDecorator(IService decoratee) { }
}
Or you can make the Setting a static property:
ServiceDecorator.Setting = setting;
container.RegisterDecorator(typeof(IService), typeof(ServiceDecorator));
If the decorator itself can't be changed, you can derive from that class:
public ServiceDecoratorWithSetting : ServiceDecorator {
public static string Setting { get; set; }
public ServiceDecorator(IService decoratee) : base(Setting, decoratee) { }
}
ServiceDecoratorWithSetting.Setting = setting;
container.RegisterDecorator(typeof(IService), typeof(ServiceDecoratorWithSetting));
A last option is to override parameter injection behavior, but that's a bit more complex, and I usually only advice this in integration scenarios.
With Autofac IoC container, say one has the following scenario:
public interface IHaveASpecialProperty
{
SpecialType SpecialProperty { get; }
}
public class HaveASpecialPropertyImpl : IHaveASpecialProperty
{
// implementation
}
public class SomeComponent
{
public SomeComponent(SpecialType special)
{
_special = special;
// rest of construction
}
private readonly SpecialType _special;
// implementation: do something with _special
}
// in composition root:
containerBuilder.RegisterType<HaveASpecialPropertyImpl>
.As<IHaveASpecialProperty>();
containerBuilder.RegisterType<>(SomeComponent);
Is there a way to register, within Autofac container, the HaveASpecialPropertyImpl type to act as a kind of provider/ factory of SpecialType instances?
What I currently have is this classic approach:
public class SomeComponent
{
public SomeComponent(IHaveASpecialProperty specialProvider)
{
_special = specialProvider.SpecialProperty;
// rest of construction
}
private readonly SpecialType _special;
// implementation: do something with _special
}
The rationale is basically related to the Law of Demeter: specialProvider is used only to grab a SpecialType instance, which instead is the actual dependency needed and used by SomeComponent, so it seems reasonable to just inject that SpecialType instance, without concerning SomeComponent on where that instance comes from.
PS: I've read about Delegate Factories, not sure if that's the (only?) way to go.
You can register a delegate :
builder.Register(c => c.Resolve<IHaveASpecialProperty>().SpecialProperty)
.As<ISpecialType>();
Using this registration, each time you will resolve a ISpecialType Autofac will resolve a IHaveASpecialProperty and return the SpecialProperty property value as ISpecialType.