Ok so I have looked at many posts on how to get DI working with web API. Trying to do simple ctor injection. What I am pasting here works but that doesn't mean I am happy with it. If anyone has some advice please sound off.
It appears we don't have to take control over controller creation in WEB API, which makes me question the proper releasing of dependencies. I have things setup as scoped, you will see by looking at the code. We are forced to use IDependencyResolver which I think sucks but this is the only workaround I can find as no other hooks that I have tried with IControllerActivator seem to work.
SEE CODE.
public class WindsorWeApiResolver:WindsorWebApiDependencyScope,IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorWeApiResolver(IWindsorContainer container) : base(container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorWebApiDependencyScope(_container);
}
}
public class WindsorWebApiDependencyScope:IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorWebApiDependencyScope(IWindsorContainer container)
{
_container = container;
_scope = _container.BeginScope();
}
public void Dispose()
{
_scope.Dispose();
}
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>().ToArray();
}
}
I agree that IDependencyResolver is not ideal. I tried to negate the lack of release method, without fighting MVC, by using the Typed Factory Facility for the scope. See my post here. Your controllers can take constructor args as usual.
You can find a constructor injection implementation sample:
http://nikosbaxevanis.com/2012/07/16/using-the-web-api-dependency-resolver-with-castle-windsor-scoped-lifetime/
Related
I realize the question may be confusing and the word "better" may be problematic, but I could not think of a, well, better way to ask.
Let's say you are writing an application that has a single entry point, like Main, which also serves as the composition root for IoC:
From outside, run application
Main or equivalent
var container = new AwesomeContainer();
container.Install(new CompositionRootInstaller(startArgs));
container.Register( ... );
ApplicationMiddleware = container.Resolve<IMiddleware>();
ApplicationMiddleware.SignalStart();
Here, ApplicationMiddleware might be a ControllerFactory in a web application, for instance.
Now, of course we will have lots of other services located by the container at the appropriate time (per request, for instance).
Sometimes we will run into situations where we don't feel like it's so bad to just assign, say, a default value to a field. But, in my view, this breaks IoC a little bit.
So, is it a true statement that (regardless of the marginal value of doing so) it is always better to avoid calling constructors or factories that call constructors or otherwise get components without calling the container once we leave the entry point?
Example: WinForms program
Here is the setup. It is a contrived example but I'm trying to focus on the issue at hand...
static class Program
{
[STAThread]
static void Main(string[] args)
{
using (var root = new AppCompositionRoot())
{
}
}
}
class AppCompositionRoot : IDisposable
{
private IWindsorContainer _container;
public AppCompositionRoot(IWindsorContainer container = null)
{
_container = container ?? new WindsorContainer();
}
public void Run()
{
var formFactory = _container.Resolve<DefaultFormFactory>();
Application.Idle += delegate
{
formFactory.ApplicationIsIdle();
};
Application.Run();
}
public void Dispose()
{
_container?.Dispose();
}
}
public interface IFormFactory
{
System.Windows.Forms.Form Create();
}
public class DefaultFormFactory : IFormFactory
{
private readonly IWindsorContainer _container;
private Form _lastForm;
public DefaultFormFactory(IWindsorContainer container)
{
_container = container;
}
public Form Create()
{
return _container.Resolve<AppForm>();
}
public void ApplicationIsIdle()
{
_lastForm = _lastForm ?? Create();
_lastForm.Show();
}
}
public class AppForm : Form
{
private readonly string _big; // sensible default is "Welcome!"
private readonly string _little; // sensible default is a string varying by form, time of day, factory
private readonly IList<object> _watched; // sensible default is list empty.
public AppForm(string bigMessage, string littleMessage, IList<object> watched)
{
_big = bigMessage;
_little = littleMessage;
_watched = watched;
}
public void Initialize()
{
// do something with bigMesaage, littleMessage, etc.
}
}
So let's start with concrete AppForm. It needs two strings and a List<object>.
Let's say for all of them there is a natural default that makes sense like 95% of the time, as in something that would be a const string on the class.
Regardless my question is - to really do IoC in the ideal sense, wouldn't it be true that you should always see constructors like these (clean constructors) and any defaults should be injected as well?
Inversion of Control simply states that control (whatever that is) is inverted. It doesn't mean that you have to invert everything; you should invert that which you want to vary.
If you're writing a Hello world application, and you don't want to vary anything, you can create the string within the implementation:
Console.WriteLine("Hello, world!");
On the other hand, if you want to be able to vary the message, you can pass it in as a Primitive Dependency:
public class Helo
{
private readonly string message;
public Helo(string message)
{
this.message = message;
}
public void SayHello()
{
Console.WriteLine(this.message);
}
}
If it helps, Miško Hevery makes the distinction between newables and injectables. On a different note, in my book, I've attempted to make a distinction between stable and volatile dependencies.
You can new up values that you don't need to be able to control from the outside. If you need to control them from the outside (Inversion of Control, remember), then you need to inject them.
I'm trying to integrate TinyIoc with MvvmCross. I followed the instructions from
https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup#changing-the-ioc-container-that-mvvmcross-uses
and created an adapter
public class TinyIoCMvxIoCAdapter : MvxSingleton<IMvxIoCProvider>, IMvxIoCProvider
{
...
}
that implements all the methods and forwards it to the TinyIoC container. That was very straight forwared and I only had to implement some additional code to fire the callbacks when something gets subscribed for
void CallbackWhenRegistered<T>(Action action)
void CallbackWhenRegistered(Type type, Action action)
I changed Setup.cs
protected override IMvxIoCProvider CreateIocProvider()
{
var provider = TinyIoCAdapterSetup.CreateIocProvider();
return provider;
}
with
public class TinyIoCAdapterSetup
{
public static IMvxIoCProvider CreateIocProvider()
{
var container = TinyIoCContainer.Current;
container.AutoRegister(t => t == typeof(IMvxViewModel));
return new TinyIoCMvxIoCAdapter(container);
}
}
That all works great. I can see that register is called on TinyIoc and things are getting resovled as well.
What does not work are the plugins. We are using the Messenger plugin and with the TinyIoC integration, the IMvxMessenger cannot be resolved when a ViewModel is resolved that gets the IMvxMessenger ctor injected. I can see that the MessengerPluginBootstrap is created by Mvx but I couldn't see that a call was made to register IMvxMessenger.
Does anybody know what I'm doing wrong?
Each plugin has a PluginLoader class that the Bootstrapper calls to register the plugin in the IoC container.
It looks something like this:
public class PluginLoader
: IMvxPluginLoader
{
public static readonly PluginLoader Instance = new PluginLoader();
private bool _loaded;
public void EnsureLoaded()
{
if (_loaded)
{
return;
}
Mvx.RegisterSingleton<IMvxMessenger>(new MvxMessengerHub());
_loaded = true;
}
}
Without seeing your IoC adapter, it's difficult to say what the issue is. Try manually registering the plugin to see if the IoC container is working properly.
Hi have the following component registered into Castle Windsor:
public class CommandDispatcher : IServiceCommandDispatcher
{
private readonly IWindsorContainer container;
public CommandDispatcher(IWindsorContainer container)
{
this.container = container;
}
#region IServiceCommandDispatcher Members
public void Dispatch<TCommand>(TCommand command) where TCommand : IServiceCommand
{
var handler = container.Resolve<IServiceCommandHandler<TCommand>>();
handler.Handle(command);
}
#endregion
}
And the dispatcher is registered in the following way:
Component
.For<IServiceCommandDispatcher>()
.ImplementedBy<CommandDispatcher>(),
But the field container is null when I resolve an instance of the dispatcher.
What should I do in order to pass the container to the resolved children items?
Windsor solves this problem for you with the Typed Factory Facility.
In the below example I want the implementation of ICommandHandlerFactory to resolve my command handler from my windsor container.
class CommandDispatcher : IServiceCommandDispatcher
{
private readonly ICommandHandlerFactory factory;
public CommandDispatcher(ICommandHandlerFactory factory)
{
this.factory = factory;
}
public void Dispatch<T>(T command) where T : IServiceCommand
{
var handler = this.factory.Create(command);
handler.Handle(command);
this.factory.Destroy(handler);
}
}
To achieve this I only need to create the ICommandHandlerFactory Interface.
public interface ICommandHandlerFactory
{
Handles<T> Create<T>(T command) where T : IServiceCommand;
void Destroy(object handler);
}
No implementation of ICommandHandlerFactory is required as Windsor will create the implementation. Windsor uses the convention that a method that returns an object is a resolve method and a method that returns void is a release method.
To register the factory you need to include using Castle.Facilities.TypedFactory and then register your factory as follows
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<ICommandHandlerFactory>()
.AsFactory()
);
Just to reiterate you do not have to write any implementation code for your factory.
This works:
container.Register(Component.For<IWindsorContainer>().Instance(container));
It's not ideal, because you still have to call the Resolve method. There may be a better way to do this, using a factory. This looks similar to what you're trying to do:
http://kozmic.net/2010/03/11/advanced-castle-windsor-ndash-generic-typed-factories-auto-release-and-more/
We are using the NoTrackingReleasePolicy on the Windsor container due to the memory leaks that occur when we do not Release our components after usage. Now consider the following problem.
Some disposable component:
public class DisposableComponent : IDisposable
{
private bool _disposed;
public bool Disposed
{
get { return _disposed; }
}
public void Dispose()
{
_disposed = true;
GC.SuppressFinalize(this);
}
}
Some class using the disposable component:
public class ClassWithReferenceToDisposableService
{
private DisposableComponent _disposableComponent;
public ClassWithReferenceToDisposableService(DisposableComponent disposableComponent)
{
_disposableComponent = disposableComponent;
}
}
And finaly a test which configures these components as transient and resolve/release them:
[Test]
public void ReleaseComponent_ServiceWithReferenceToTransientDisposable_TransientComponentDisposed()
{
// arrange
var windsorContainer = new WindsorContainer();
windsorContainer.Kernel.ReleasePolicy = new NoTrackingReleasePolicy();
windsorContainer.Register(Component.For<ClassWithReferenceToDisposableService>().LifeStyle.Transient);
windsorContainer.Register(Component.For<DisposableComponent>().LifeStyle.Transient);
ClassWithReferenceToDisposableService service =
windsorContainer.Resolve<ClassWithReferenceToDisposableService>();
// act
windsorContainer.Release(service);
}
Now, if I remove the NoTrackingReleasePolicy, Windsor will dispose the transient service as expected, but I can not do this (period). Now, what I want to achieve is that Windsor disposes the transient components (anywhere in the resolve graph) when I invoke ReleaseCompnent. Is there any way to achieve this without changing the NoTrackingReleasePolicy?
No, you can't have your cake and eat it too.
You can implement your own custom policy that is kind of like NoTrackingReleasePolicy but will track some components...
Consider the following example:
public interface ITask
{
void Execute();
}
public class LoggingTaskRunner : ITask
{
private readonly ITask _taskToDecorate;
private readonly MessageBuffer _messageBuffer;
public LoggingTaskRunner(ITask taskToDecorate, MessageBuffer messageBuffer)
{
_taskToDecorate = taskToDecorate;
_messageBuffer = messageBuffer;
}
public void Execute()
{
_taskToDecorate.Execute();
Log(_messageBuffer);
}
private void Log(MessageBuffer messageBuffer)
{}
}
public class TaskRunner : ITask
{
public TaskRunner(MessageBuffer messageBuffer)
{
}
public void Execute()
{
}
}
public class MessageBuffer
{
}
public class Configuration
{
public void Configure()
{
IWindsorContainer container = null;
container.Register(
Component.For<MessageBuffer>()
.LifeStyle.Transient);
container.Register(
Component.For<ITask>()
.ImplementedBy<LoggingTaskRunner>()
.ServiceOverrides(ServiceOverride.ForKey("taskToDecorate").Eq("task.to.decorate")));
container.Register(
Component.For<ITask>()
.ImplementedBy<TaskRunner>()
.Named("task.to.decorate"));
}
}
How can I make Windsor instantiate the "shared" transient component so that both "Decorator" and "Decorated" gets the same instance?
Edit: since the design is being critiqued I am posting something closer to what is being done in the app. Maybe someone can suggest a better solution (if sharing the transient resource between a logger and the true task is considered a bad design)
Edit2: Castle3 has added support for this (http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx) by introducing the "Bound" lifestyle
'Transient' explicitly means 'non-shared', so what you are asking is conceptually the wrong thing to do. The correct solution is to register Shared as a Singleton instead of Transient:
container.Register(Component.For<Shared>());
(Singleton is the default lifetime in Windsor.)
However, I suspect that behind the stated question lies a much more complex problem. I'm guessing that you need Shared to be Transient because you need it with this lifestyle for a lot of other cases, but exactly when it comes to the relationship between Decorator and Decorated you need to share them.
I still think this sounds like a Design Smell, but there are at least two ways you can achieve this result.
The first option involves prematurely resolving Shared and explicitly supply the resolved instance to the configuration of the two IFoo registrations:
container.Register(Component.For<Shared>().LifeStyle.Transient);
var r = container.Resolve<Shared>();
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorator>()
.DependsOn(new { resource = r }));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorated>()
.DependsOn(new { resource = r }));
The second option is to make a specialized, named registration for Shared that is used only by the IFoo registrations:
container.Register(Component.For<Shared>().LifeStyle.Transient);
container.Register(Component.For<Shared>().Named("shared"));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorator>()
.ServiceOverrides(new { resource = "shared" }));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorated>()
.ServiceOverrides(new { resource = "shared" }));