Tim M.
Tim M.

Reputation: 54377

Ninject 3 activation context contains unexpected type information

Setup

I want to pass an instance of a cache as a dependency to one or more types. When a concrete instance of the cache is instantiated, it must be provided information about the type that will use it.

I realize that this a common task and that injecting cache dependencies appears in various questions/answers; I'm setting up a specific problem I'm having with Ninject.

interface IMethodCache { }

public class MethodCache : IMethodCache
{
    public MethodCache( Type type )
    {
        // type information is used to build unique cache keys
    }
}

public class CacheConsumer
{
    public CacheConsumer( IMethodCache cache ) { }
}

Documentation

The Ninject documentation shows how to do just that (using logging as an example):

class ClassThatLogs {
    readonly ILog _log;
    public ClassThatLogs(ILog log){
        _log = log;
    }
}

Bind<ILog>().ToMethod( context => LogFactory.CreateLog( context.Request.Target.Type ) );

The previous example shows that context.Request.Target.Type will contain the type information for the type into which injection occurs.

Furthermore, the comments on context.Request.Target state:

Gets the target that will receive the injection, if any.

Results

Based on this, I expect to see information about the instance receiving the injection. I setup my binding as follows:

kernel.Bind<IMethodCache>().ToMethod( 
  ctx =>
  {
      return new MethodCache( ctx.Request.Target.Type );
  } );

But the result is unexpected.

enter image description here

The Type property of Target is set to the type being bound (IMethodCache), not the "target that will receive injection" (CacheConsumer).

To state it another way: when the dependency is created, I need to pass the injectable's type to it.

I can obtain the desired information by using context.Request.Target.Member.DeclaringType. However, I'm concerned because I don't know the ramifications of relying on the declaring type and—more importantly—because this seems contrary to the documentation.

Questions

Other Details

Upvotes: 2

Views: 475

Answers (1)

nemesv
nemesv

Reputation: 139758

Yes, it seems that the documentation is incomplete/incorrect in this case.

you can get the "target" type information starting from ctx.Request.Target property but but you need to go "one step further" with using the Member and the ctx.Request.Target.Member.DeclaringType as you've already noticed.

So it is completely fine to use the context.Request.Target.Member.DeclaringType in fact if you check the mentioned Ninject.Extensions.Loggin you will see the following in the

source code:

/// <summary>
/// Gets the logger for the specified activation context, creating it if necessary.
/// </summary>
/// <param name="context">The ninject creation context.</param>
/// <returns>The newly-created logger.</returns>
public ILogger GetLogger(IContext context)
{
    return this.GetLogger(context.Request.Target.Member.DeclaringType);
}

Upvotes: 4

Related Questions