Search code examples
inversion-of-controlnancytinyioc

Getting TinyIoc current container in a Nancy project


I'm building a small Nancy web project.

In a method of one of my classes (not a nancy module), I would like to basically do:

var myThing = TinyIoC.TinyIoCContainer.Current.Resolve<IMyThing>();

However, there is only one registration in .Current (non public members, _RegisteredTypes) which is:
TinyIoC.TinyIoCContainer.TypeRegistration

Naturally, in my above code, I'm getting:

Unable to resolve type: My.Namespace.IMyThing

So, I guess I'm not getting the same container registered in my bootstrapper?

Is there a way to get at it?

EDIT

To flesh out a bit more of what I'm trying to do:

Basically, my url structure looks something like:

/{myType}/{myMethod}

So, the idea being, going to: /customer/ShowAllWithTheNameAlex would load the Customer service, and execute the showAllWithTheNameAlex method

How I do this is:

public interface IService
{
    void DoSomething();
    IEnumerable<string> GetSomeThings();
}

I then have an abstract base class, with a method GetService that returns the service.
It's here that i'm trying to use the TinyIoC.TinyIoCContainer.Current.Resolve();
In this case, it would be TinyIoC.TinyIoCContainer.Current.Resolve("typeName");

public abstract class Service : IService
{
    abstract void DoSomething();
    abstract IEnumerable<string> GetSomeThings();

    public static IService GetService(string type)
    {
        //currently, i'm doing this with reflection....
    }
}

Here's my implementation of the service.

public class CustomerService : Service
{
    public void DoSomething()
    {
        //do stuff
    }

    public IEnumerable<string> GetSomeThings()
    {
        //return stuff
    }

    public IEnumerable<Customer> ShowAllWithTheNameAlex()
    {
        //return
    }
}

Finally, I have my Nancy Module, that looks like:

public class MyModule : NancyModule
{
    public MyModule()
    {
        Get["/{typeName}/{methodName}"] = p => ExecuteMethod(p.typeName, p.methodName);
    }

    private dynamic ExecuteMethod(string typeName, string methodName)
    {
        var service = Service.GetService(typeName);

        var result = service.GetType().GetMethod(methodName).Invoke(service, null);

        //do stuff

        return result; //or whatever
    }
}

Solution

  • @alexjamesbrown - The short answer is, you don't. Nancy was specifically designed so that you did not deal with the container directly. You mention that the class, that you want to take a dependency on IMyThing, is not a NancyModule. Well this is not an issue, as long as one of your modules has a reference to it, then those dependencies can also have their own dependencies that will be satisfied at runtime.

    public interface IGreetingMessageService
    {
       string GetMessage();
    }
    
    public class GreetingMessageService: IGreetingMessageService
    {
       public string GetMessage()
       {
          return "Hi!";
       }
    }
    
    public interface IGreeter
    {
       string Greet();
    }
    
    public class Greeter
    {
       private readonly IGreetingMessageService service;
    
       public Greeter(IGreetingMessageService service)
       {
          this.service = service;
       }
    
       public string Greet()
       {
          return this.service.GetMessage();
       }
    }
    
    public class GreetingsModule : NancyModule
    {
       public GreetingModule(IGreeter greeter)
       {
          Get["/"] = x => greeter.Greet();
       }
    }
    

    The above will work just fine and Greeter will have it's dependency on IGreetingMessageService satisfied at runtime