I am experiencing an issue, and I have come to a dead end on how to debug and resolve this.
I have an MVC application which is using Ninject for IoC and DI.
One of my dependencies is IApplicationLogger which I am currently implementing using Log4Net.
In my NinjectWebCommon I am binding my IApplicationLogger as follows:
kernel.Bind<IApplicationLogger>()
.ToMethod(ctx =>
{
string configFile = System.Configuration.ConfigurationManager.AppSettings["log4netconfigfilelocation"];
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(HttpContext.Current.Server.MapPath(configFile)));
var name = ctx.Request.Target.Member.DeclaringType.FullName;
var log4Netlogger = log4net.LogManager.GetLogger(name);
return new Log4NetApplicationLogger(log4Netlogger);
}).InTransientScope();
All fairly straight forward stuff.
However, I am finding that the first instance of IApplicationLogger which is activated is then passed to all constructors which require an IApplicationLogger instance.
for example I have the following
public class A : IA
{
public A(IB bclass, IC cclass, IApplicationLogger logger){}
}
public class B : IB
{
public B(IApplicationLogger logger){}
}
public class C : IC
{
public C(IApplicationLogger logger){}
}
I have set breakpoints on each constructor and also the line in my NinjectWebCommon kernel.Bind().ToMethod(ctx =>
What I see is this:
Break point in NinjectWebCommon is hit, and I can see
ctx.Request.Target.Member.DeclaringType.FullName is Class B.
Break point in Constructor Class B is hit and logger
instance is correct
Break point in Constructor Class C is hit, and
logger instance has a logger name of Type Class B
Break point in Constructor Class A is hit, and logger instance has a logger
name of Class B
I would expect the breakpoint within NinjectWebCommon to be hit for each new instance of IApplicationLogger that is required, but it is only hit once for the first activation for the instance of Class B.
I have tried my Binding without the InTransientScope() option.
My IA, IB and IC bindings are defined InSingletonScope(). This shouldn't cause an issue as I am expecting Ninject to activate an instance of each, each with it's own instance of IApplicationLogger.
The result of the binding I am seeing currently is that logging statements I output in say Class A are being recorded in the Log as being from a logger name for class of type B.
Can anyone suggest how I can diagnose why Ninject is reusing the TransientScoped() IApplicationLogger, or how I can peek under the hood of what Ninject is doing so that I can analyse this in greater detail?
For anyone interested I didn't discover the underlying issue here, but I have opted to inject an ILoggerFactory with a single method .GetLogger(string typename), allowing my classes to request their own Logger and passing their own Type name.
This way I can ensure that each Class has it's own logger, with the LoggerName matching the Class TypeName.
Related
I am trying dagger in one of my projects and i am experiencing this situation:
"Field injection only works if I declare the class as an entry point in the module definition."
Is this the correct behaviour?
The below dependencies are not injected to Messenger class if Messenger.class is not declared as an entry point. Constructor injector works fine but I don't want to declare a multi parameter constructor.
public class Messenger implements NetworkInterfaceListener {
#Inject public NetworkInterface networkInterface;
#Inject public MessageFactoryInterface messageFactory;
#Inject public Bus bus;
#Inject public Logger log;
...
...
}
You have only two alternatives: either to declare injectable constructor with all params to be injected or enlist class into entryPoints (now called injects) of your dagger module and call mGraph.inject(this) in default constructor (or whenever you need to actually "inject" maybe even outside the class).
I have an interface
public interface ILoggerService
{
void Info(string message);
void Warn(string message);
}
Then, i have a class which implements this interface and logs using Log4Net
public class Log4NetLoggerService : ILoggerService
{
private readonly ILog _logger;
public Log4NetLoggerService()
{
// this always returns Log4NetLoggerService class type
_logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public void Info(string message)
{
_logger.Info(message);
}
}
This works fine, but the problem is that if i want to log the current class and method name, (using %class - %M), this always returns Log4NetLoggerService as the class, and as the method it returns Info as the method.
I need to get the "parent" class type, which called the logging method.
Can i inject somehow the type of the class which calls the log methods when i create the ILoggerService instance?
Have a look at the log4net source code; specifically how they implemented the ILog interface. You basically cannot use the ILog interface in your wrapper, instead you use the internal logger which accepts a parameter that instructs log4net where to look for the correct class / method in the call stack. See also this answer.
In my experience, if you need the name of the class you're logging in, you're probably logging too much and from too many places in your application. This can lead to maintenance problems. Take a look at this Stackoverflow answer to verify if you're not logging too much and if you're not violating the SOLID principles.
I have a repository like:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
private readonly IContext _db;
public Repository(IContext context)
{
_db =context;
}
...
In Global.asax I have setup the ninject as:
kernel.Bind<IContext>().To<Context>();
This is working fine in the app probably because I'm explicity instantiating by calling the constructor with a paramater. There are problems in the unit tests however.
Then in a unit test I have:
var mockUnitOfWork = new Mock<UnitOfWork>();
var mockProjectApprovalRepository = new Mock<Repository<ProjectApproval>>();
mockUnitOfWork.Setup(x => x.ProjectApprovalRepository).Returns(mockProjectApprovalRepository.Object);
On this last line I get the error:
Can not instantiate proxy of class: MyNamespace.Repository Could not find a parameterless constructor.
I'm confused by this because I thought the point of Ninject was I didn't need to specify a parameterless constructor. Shouldn't ninject have instantiated a Context and used the constructor with one parameter.
When you do new Mock<Repository<ProjectApproval>>(), you're asking Moq to construct the object. If you asked Ninject to construct it, it would do it.
Ninject doesn't magically step in wherever construction happens - new is still new.
In this case, you can use an overload of the Mock constructor wherein you specify extra args.
Note that its generally accepted that Ninject shouldnt be anywhere near anything remotely close to the any common definition of the term Unit Test.
In my MVC3 app I have an IDataRepository interface which is referenced by all my controllers to give them access to the data layer. There's also a DataRepository class which is implements IDataRepository for a particular data source (an nHydrate-derived Entity Framework, in my case). The DataRepository class takes a single argument, which is the connection string to the underlying database.
I've been successfully using nInject to to IoC with the controller classes using the following binding:
kernel.Bind<IDataRepository>()
.To<DataRepository>()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
Today I read about nInject scoping, and I thought it would be useful to arrange things so that only one instance of DatabaseRepository got created for each request (I'm thinking this will be more efficient, although with EF I'm not sure).
Unfortunately, I can't seem to figure out how to implement the pattern correctly. For example, this doesn't work:
kernel.Bind<DataRepository>()
.ToSelf()
.InRequestScope()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
kernel.Bind<IDataRepository>()
.To<DataRepository>();
My thinking was that this would create just a single instance of DataRepository, which would be used in all references to IDataRepository. The error message complained that no match could be found for the connectionString parameter, and DataRepository was not self-bindable. I tried some variations, but when I could get it to work the singleton pattern wasn't being followed (i.e., I could see in the debugger that multiple instances of DataRepository were being created).
I'm missing something obvious here :).
--- Addendum ---
Unfortunately, the suggestion doesn't prevent multiple instances from being created within the same request.
To be clear, what I tried was:
public class BaseControllerModule : NinjectModule
{
public override void Load()
{
Bind<IDataRepository>().To<DataRepository>().InRequestScope()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
}
}
and what I was monitoring was the constructor:
public DataRepository( string connectionString )
: base(connectionString)
{
}
-- More info #2 --
Here's the layout of the classes Ninject is resolving for me:
public class DataRepositoryBase
{
protected DataRepositoryBase( string connectionString )
{}
public static string GetConnectionString() {}
}
public class DataRepository : DataRepositoryBase, IDataRepository
{
public DataRepository( string connectionString )
: base(connectionString)
{}
}
I've left out the implementation details, but hopefully this paints a better picture.
Looking this over, I wonder if I'm causing problems by making connectionString a constructor parameter for both DataRepository and its base class DataRepositoryBase. Wouldn't Ninject resolve connectionString in the call the base class constructor?
p.s. I belatedly realized I don't need DataRepositoryBase, because its functionality can be merged into DataRepository. I've done that, but I'm still having the constructor for DataRepository called multiple times in what appears to be one request.
p2.s. For fun, I tried declaring InSingletonScope() in the Ninject binding definition. That worked -- the constructor for DataRepository now only gets called once, when the app is first accessed. But I don't think it's a good idea to have singletons in an MVC app. It seems like that would cause the "state" of the app to get "locked" in memory.
--- yet more info ---
The problem seems to be with the way I've designed my MVC app. What I assumed was a single request from the browser back to the server often results in multiple requests being processed in sequence (I'm watching the BeginRequest event being fired in the MvcApplication class). It seems like every time I transition to a different controller a new request is being generated (e.g., via a RedirectToAction). I guess this makes sense, but it means Ninject's InRequestScope won't quite do what I want.
But it also makes me wonder if I've just designed the app wrong. It seems like I should be grouping all of the action methods that might get invoked on a browser call into a single controller. Instead, I've organized the action methods by how they fit into the conceptual model for my app.
These two bindings say:
When a DataRepository is requested reuse the instance for all occurances within the request and set the connection string to DataRepositoryBase.GetConnectionString().
But when a IDataRepository is requested, create a new instance for every occurance and let Ninject decide what it injects for the connection string.
What you really want is done by adding InRequestScope to the first code snippet.
Wouldn't that be sufficient to have a singleton?
kernel.Bind<IDataRepository>()
.To<DataRepository>()
.InSingletonScope()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
RequestScope is not a singleton, it means that the objects are separate for each user's call.
By the way, I think the real repository shouldn't be singleton - it should rather follow the Unit of Work pattern, meaning that its lifetime should represent one higher-level data operation and the connection itself should be at lower level than repository.
i have a code like this, but giving error can not access protected member.
**Class A
{
protected void m1()
{
some code
}
}
Class B:A
{
B b=new B();
b.m1();// Ok works fine
A a =new a();
a.m1();/// don't work, compile time error
A a2=new B();
a2.m1(); //compile time error, don't work
}**
just not getting reason behind this, Why so aberrant nature of the above code, why a method of a class using same class object not accessible out side. While i searched a bit for this but did not undersand, i found something that compiler nature come in picture, but i did not understand.
you can prefix your call by base keyword for calling base members. protected means that a member could be inherited by descendants and could be called but through the specified way.
calling a.m1() in your class hasn't any difference with calling it form an out of B code.
As stated above, the protected method inside the class can only be accessed by the class that inherits the original container.In your case B is the sub class, a is your base. Inside your B class you are creating a new instance of A class ('a'), and this is now a different object (B class does not care about this new object A). This new object 'a' will not expose the protected method, so 'a.m1()' will throw a compile error.