NancyFx and TinyIoC provide single instance to module - c#

Iv got a fairly simlpe question. Im using Nancy with a windows form (passed through the constructor (autoresolve)). If i let nancy resolve automatically every module it creates a new instance of the form, which is not what i want. I thought maybe i could register my form instance in TinyIoC and then it would always use just this instance instead of creating a new one each time. But that has proved not as simple to implement as the idea is.
Thanks in advance

you should probably do this in the bootstrapper
something like:
public class MyBootstrapper: DefaultNancyBootstrapper
{
ConfigureApplicationContainer (TinyIoCContainer container)
{
//the .AsSingleton() instructs TinyIOC to make only one of those.
container.Register<IMessageDeliverer>().AsSingleton();
base.ConfigureApplicationContainer (container);
}
}

I resolved this by not assigning the window reference to the contructor but by registering it with TinyIoC and the resolving it in the default constructor
//Registering in form
var container = TinyIoCContainer.Current;
container.Register<IMessageDeliverer>(this);
//Resolving in Module Constructor
var container = TinyIoCContainer.Current;
IMessageDeliverer mdl = container.Resolve<IMessageDeliverer>();
setDeliverer(mdl);

Related

Simple Injector Container Fails To Register Web API Controller From Pluggedin External Library

The issue was noticed with the call to the extension method container.RegisterWebApiControllers(GlobalConfiguration.Configuration) on the container that's supposed to register the web api controller with the container but didn't. Please note that the web api controllers are defined in a different class library project and plugged at application start up using a custom IAssembliesResolver type.
public static class SimpleInjectorWebApiInitializer
{
public static void Initialize()
{
var container = new Container();
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver),
new ApiAssemblyResolver());
InitializeContainer(container);
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
I even tried to call to get the ControllerTypes manually to see what was going on using the code below but it never triggered the GetAssemblies method neither did it return any ControllerTypes.
var controllerTypes = httpConfigServicesContainer.GetHttpControllerTypeResolver()
.GetControllerTypes(
GlobalConfiguration.Configuration.Services.GetAssembliesResolver());
I am almost pulling out all my hair as I can't seem to see what I am doing wrong. Thanks for your help in advance.
It's hard to be very specific, but here's a list of things that might be causing your controllers to not be registered:
Your ApiAssemblyResolver does not return the assembly that holds the controllers.
That assembly is a dynamic assembly (meaning that Assembly.IsDynamic returns true). Web API will skip dynamic assemblies.
The controller types are internal. Web API only uses public types.
The controller types are not classes (but structs).
Their type name does not end with "Controller"
They don't implement IHttpController.
Your IAssembliesResolver isn't registerd correctly (perhaps you are missing a binding redirect, causing your application to reference two versions of Web API). Tip: Check what for type GlobalConfiguration.Configuration.Services.GetAssembliesResolver() actually resolves.
Also try the following:
var controllerTypes = httpConfigServicesContainer.GetHttpControllerTypeResolver()
.GetControllerTypes(new ApiAssemblyResolver());
Does this result in any controllers? In that case, there is probably something miss with the call to Replace(typeof(IAssembliesResolver).
The solution lay in the order in which configuration calls were made. I moved every call for configuration involving the IOC container into the Application_Start method of Global.asax file.
Before making the call to GlobalConfiguration.Configure(WebApiConfig.Register),
I had already called
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new ApiAssemblyResolver())
to replace the default assemblies resolver. I finally placed the other container web api configuration settings after every other configuration call and it started working like a charm! I.e
var apiIOCContainer = new Container();
SimpleInjectorWebApiInitializer.InitializeContainer(apiIOCContainer);
apiIOCContainer.RegisterWebApiControllers(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(apiIOCContainer);

Simple Injector and default AccountContoller dependency issue

I have problem with Simple Injector in my Web Api project. I user default AccountController generated by VS.
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
In my configuration file I register:
var container = new Container();
// This is an extension method from the integration package.
container.RegisterWebApiFilterProvider(config);
container.RegisterWebApiControllers(config);
container.Register<IInitializeService, InitializeService>();
container.Register<IFolderRepository, FolderRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<ILogger, Logger>();
//Authentication Wrap
container.Register<IUserStore<User, Guid>, ApplicationUserStore>();
container.Register<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.Register<ISecureDataFormat<AuthenticationTicket>,
SecureDataFormat<AuthenticationTicket>>();
container.Register<IDataProtector>(
() => new DpapiDataProtectionProvider().Create("ASP.NET Identity"));
container.Verify();
// 4. Register the container as MVC3 IDependencyResolver.
DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container));
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
I though that Simple Injector will be smart enough to handle all build in dependences responsible for default identity and i wont need to register them manually, but I'm getting exceptions if I wont register them.
Still getting an exception:
The constructor of type SecureDataFormat contains the parameter of type ITextEncoder with name 'encoder' that is not registered. Please ensure ITextEncoder is registered in the container, or change the constructor of SecureDataFormat.
Is there any way to handle that automatically?
I implemented a Web Api and I wrote this code.
This works for me
container.RegisterWebApiRequest<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
container.RegisterWebApiRequest<ITextEncoder, Base64UrlTextEncoder>();
container.RegisterWebApiRequest<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.RegisterWebApiRequest<IDataProtector>(() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider().Create("ASP.NET Identity"));
How is the container supposed to know which implementation of ITextEncoder you want to use in the constructor of SecureDataFormat?
You have to tell it which one to use. I think the rules basically go something like this:
if an interface is required (by a constructor) then it needs to know which implementation to use. If a concrete class is required it will automatically build an instance of that class (assuming it can resolve all the types that class needs).
As your SecureDataForms needs an interface you have to register one, otherwise its only option would be to 'guess' at which implementation you want and this could then go wrong silently if more than one implementation existed.
I just came up against this issue. I'm using ninject but you'll get the idea. Here is my binding:
kernel.Bind<ITextEncoder>().To<Base64UrlTextEncoder>();
According to the source, the only thing I ever see being used to new up an instance of SecureDataFormat is Base64UrlTextEncoder. So it seemed like a safe bet to use, but it's certainly not clear to me at first glance how to appropriately use this constructor overload.

Unity can't resolve interface in Session_Start and resolves wrong DbContext

I'm using Mvc3 and Unity.Mvc3 to build a testable and decoupled site, but I'm obviously doing something wrong.
In my Application_Start() i register a dependency:
// container is a property of the MvcApplication
// and the HierarchicalLifetimeManager should make sure that the registrations
// only last for this request (or should it?)
_container.Register<Interface, Class>(new HierarchicalLifetimeManager())
Then in the Session_Start() i try to resolve my dependency to save some data into the session:
var obj = _container.Resolve<Interface>();
At this point I get an exception saying that Unity can't resolve an interface, but I thought I registered a class for that interface???
I'm at a loss, and it's getting harder and harder to find a solution.
EDIT:
Here's my whole code, with some unnecessary parts left out:
public class MvcApplication : System.Web.HttpApplication
{
// as EDIT 2 says, this is wrong...
//private IUnityContainer _container = new UnityContainer();
protected void Application_Start()
{
// mvc stuff, routes, areas and whatnot
// create container here and it works, almost
var container = new UnityContainer();
// register dependencies
string connectionString = "String from config";
container.RegisterInstance<DbContext>(new CustomContext(connectionString), new HierarchicalLifetimeManager())
.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager())
.RegisterType(typeof(IRepository<>), typeof(Repository<>), new HierarchicalLifetimeManager());
// register controller resolver
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// if i try to resolve repos here, it works and they all have the same context
// just like the unit of work
}
protected void Session_Start()
{
// here the container complains that it can't resolve the interface
// wrong
//var userRepo = _container.Resolve<IRepository<User>>();
// right, but still failes, because it is resolving DbContext
// instead of using the CustomContext instance
var userRepo = DependencyResolver.Current.GetService<IRepository<User>>();
// save some user data to session
}
}
public class SampleController : Controller {
// here the container tries to resolve the System.Data.Entity.DbContext
// instead of just giving the repo that instance that I registered
public SampleController(IRepository<Entity> repo) {
}
}
I'm obviously failing miserably at this Unit-of-work, dependency injection stuff, and the worst part is that I don't know why...
So please help before I start pulling my teeth out.
EDIT 2:
Partly there. If i create the container as above, it fails in the Session_Start(). If i create it in the Application_Start() as a local variable, and use the DependencyResolver, it works. How and why, beats me?
But it's still trying to resolve the DbContext instead of the CustomContext instance.
SOLUTION:
Ok, so here's the deal:
Problem 1) accessing the container in Session_Start():
As described in the EDIT 2, using a local container variable solves that, and accessing the container via the DependencyResolver works.
Problem 2) resolving the registered db context instance:
It turns out that registering an instance does not work.
This does though:
container.RegisterType<DbContext, CustomContext>(null, new HierarchicalLifetimeManager(), new InjectionConstructor(connectionString))
But I don't really feel satisfied, because I still didn't figure out why this works like this. Looks like I need to read a book or something for once in a long time.
Many thanks in advance.
The problem is you're using RegisterInstance with the HierarchecalLifetimeManager. I'm guessing you're trying to get a new instance per request, because the Unity.Mvc3 project uses that LifetimeManager to work that magic (as well as HttpModules to manage the creation and destruction of child containers).
The problem is, as a new request comes in, it will want to construct a new object, but doesn't know how to; you just registered an instance once, at the app start, and not a way to make an object. So you need to use RegisterType() for that to work.
You have two choices:
Specify the injected value using an InjectionConstructor: RegisterType<DbContext, CustomContext>(new HierarchecalLifetimeManager(), new InjectionConstructor(connectionString))
Use a factory: Container.RegisterType<DbContext>(new InjectionFactory(c => new CustomContext(connectionString)), new HierarcicalLifetimeManager()) (inspired by this)
*Note: parameter order may be wrong.
If you want a true singleton instance for your entire application, use the ContainerControlledLifetimeManager() (which is actually the default for RegisterInstance, so you don't even need to specify it). But then your DbContext will get rather huge as the site gets used.
Additionally, on your initial problem with the items not being registered in Session_Start():
ASP.NET maintains a pool of HttpApplication classes. That means if you make the Unity container a member variable, you'll have several instances which all have their own registrations. Application_Start() is called only once, and Session_Start() could be called using a different instance with no registrations. You'd need to use a static variable to solve that (which is what you ended up doing with the DependencyResolver).
Instead of accessing the container directly (it's not clear from your Q where you got the reference to the container?), why not let the MVC dependency resolver resolve it?
Set the Dependency resolver (Application_Start()):
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Resolve your interface (Session_Start()):
var obj = DependencyResolver.Current.GetService<IMyInterface>();

StructureMap, configure using container or objectfactory?

I did my configuration like this:
var container = new Container(x =>
{
x.For<IEngine>().Use<V6Engine>();
x.For<ICar>().Use<HondaCar>();
}
);
Then in my mvc controller action I did:
ICar car = ObjectFactory.GetInstance<ICar>();
Should I be setting up my container using Container or ObjectFactory somehow? It didn't resolve, so I tested things out in a c# console application and it worked if I did:
ICar car = container.GetInstance<ICar>();
But this only works if container is in local scope, and in a web app it isn't obviously since things are wired up in global.asax.cs
ObjectFactory is a static gateway for an instance of container. If you only ever want one instance of a container, and want a simple static way to get at it, use ObjectFactory. You must Initialize the ObjectFactory, and then retrieve your instances via ObjectFactory.
Alternatively, if you want to manage the lifetime of the container yourself, you can create an instance of Container, passing an initialization expression to the constructor. You then retrieve instances from the variable you declared to store the Container.
In your example, you are mixing the two approaches, which doesn't work.
I have got mine configured as below
global.asax
ObjectFactory.Initialize(action =>
{
action.For<ISomething>().Use<Something>;
});
Then everywhere else.
ObjectFactory.GetInstance<ISomething>();
This may not be the only way though. Also I think what you might be looking for is the
Scan(scanner =>
{
scanner.AssemblyContainingType(....);
scanner.AddAllTypesOf(....);
}

IoC - Constructor takes a runtime value as one parameter and a service as another

I have a WPF app which, when it starts, looks at the file system for some config files
For each config file it finds, it displays some info in a different window
Each window has an associated ViewModel object which is bound to the windows datacontext
So a new ViewModel is created for each config file. An object representing the data in the config file is passed into the viewmodels constructor
However, the View model also has other dependancies passed into the constructor
The code looks something like this (in a bootstrapper initiated from app.xaml)
foreach (WindowConfig config in ConfigManager.GetConfigs())
{
IMyService svc = new MyService();
//change to resolve from IoC container
MyViewModel vm = new MyViewModel(config, svc);
Window1 view = new Window1();
view.DataContext = vm;
window.show();
}
I want to use Castle IoC contaoiner resolve these dependancies. I know how to do that for IMyService, but how can I do it for the specific class that has been created from the config file ?
thanks
Always remember that in the application code, pulling from the container is never the solution. Application code should be unaware that there's a DI container in play.
The general solution when you need to resolve a dependency based on a run-time value is to use an Abstract Factory.
In your case, the factory might look like this (assuming that your config variables are strings:
public interface IViewModelFactory
{
IViewModel Create(string configuration);
}
Now you can inject the IViewModelFactory as a single dependency into the class that loops through the configuration files.
To implement IViewModelFactory you can either do it by hand or use Castle Windsor's Typed Factory Facility to implement it for you.
You can pass parameters to Windsor, that it should use when resolving the constructor, by using the overload of IWindsorContainer.Resolve that takes an IDictionary as a parameter. In this dictionary, the key should be the parameter name, and the value should be the object to use as the parameter value:
var arguments = new Dictionary<string,object> {{ "config", config }, { "service", svc } };
var viewModel = container.Resolve<MyViewModel>(arguments);

Categories

Resources