I m reading Prism library by microsoft. I just dont understand ConfigureContainer().
The code in shell application like this:
internal class JamSoftBootstrapper : UnityBootstrapper
{
protected override IModuleEnumerator GetModuleEnumerator()
{
return new DirectoryLookupModuleEnumerator("Modules");
}
protected override void ConfigureContainer()
{
Container.RegisterType<IShellView, Shell>();
base.ConfigureContainer();
}
protected override DependencyObject CreateShell()
{
ShellPresenter presenter = Container.Resolve<ShellPresenter>();
IShellView view = presenter.View;
view.ShowView();
return view as DependencyObject;
}
}
public interface IShellView
{
void ShowView();
}
public class ShellPresenter
{
public IShellView View { get; private set; }
public ShellPresenter(IShellView view)
{
View = view;
}
}
I want to understand why I register IShellView,Shell in ConfigureContainer(). Whats going on behind sceens?
I've registered to give you answer :). ConfigureContainer is just method from abstract class UnityBootstrapper where you can register all Prism services (ModuleManager, RegionManager, EventAggregator). You can make your custom Bootstrapper class, where you can manage your dependency. In your case, every time when you in your code ask for IShellView, you'll get instance of Shell.
I recommend you this book. It's free.
UnityBootstrapper provided by PRISM internally uses UnityContainer to resolve dependency for your registered objects. You can configure your custom objects with it like you are doing in sample.
In your sample, you registered Shell with instance IShellView.
Container.RegisterType<IShellView, Shell>();
So whenever you ask container to get you object for IShellView, it will give you an instance of Shell object.
IShellView shellObject = Container.Resolve<IShellView>();
So, ConfigureContainer gives you support to register your objects with it's container.
Quote from MSDN link:
Configures the IUnityContainer. May be overwritten in a derived class
to add specific type mappings required by the application.
Also, you can read more about it here - Managing Dependencies Between Components Using the Prism Library 5.0 for WPF.
Related
I'm new to dependency injection and still trying to wrap my head around it. As I understand, best practice according to the book Dependency Injection in .NET states that the object graph is created once at app startup in the Composition Root and the container is not accessed again in the application.
What happens when the user hits the new/open button?
Normally I would create new instances of the object graph portion needed (Forest) but if I'm not supposed to access the container, do I call a clear method that propagates the object graph? Do I somehow use lifetime management and make sure there are no current references to the portion of the object graph needed to be new?
Edit:
Example using MVVM/WPF
public class Bootstrapper {
public void Initialize() {
Container.Register<IMainViewModel, MainViewModel>();
Container.Register<IForest, Forest>();
Container.Register<ITrees, Trees>();
Container.Register<ITree, Tree>();
}
}
public class MainViewModel : IMainViewModel {
private IForest _forest;
public MainViewModel(IForest forest) { _forest = forest; }
public void New() { Forest.Clear(); }
public void AddTrees(){ _trees.Add(new Tree()); }
}
public class ViewModel : IViewModel {
private ITrees _trees;
private ITree _selectedTree;
public ViewModel(ITrees trees){ _trees = trees; }
public void AddTrees() { _trees.Add(new Tree()); }
}
public class Forest : IForest {
private ITrees _trees;
public Forest(ITrees trees){ _trees = trees; }
public void AddTree(ITree tree){ _trees.Add(tree); }
public void Clear(){ _trees.Clear(); }
}
public class Trees : ITrees {
public List<ITree> trees = new List<ITree>();
public void Add(ITree tree){ trees.Add(tree); }
public void Clear(){ trees.Clear(); }
}
according to the book Dependency Injection in .NET states that the object graph is created once at app startup in the Composition Root and the container is accessed again in the application.
Nowhere does the book state that an application's object graph should be created just once, and it certainly does not state that the container should be accessed from the application.
The 1st edition of the book however states the following (not exact quotes):
Objects graphs should be composed as close as possible to the application's entry point (section 3.3.1, page 75)
Object graphs are configured once (at application startup), but created (resolved) many time throughout the application's lifetime (section 3.3.2, page 84)
Asking a DI Container for granular services from anywhere else but the Composition Root implies the Service Locator anti-pattern. (section 5.4, page 155)
To summarize:
Object graphs are always composed inside the Composition Root
They are configured/registered just once, during application startup
Any time a new object graph is required, it can be composed. This means that object graphs can be composed many times during the application's lifetime
The code that requests a new object graph should always be part of the Composition Root to prevent the Service Locator anti-pattern.
but if I'm not supposed to access the container, do I call a clear method that propagates the object graph?
The answer to this seeming paradox is: Abstraction!
To be able to construct an object graph lazily from within an already-constructed component, you can define a specific Abstraction (an Abstract Factory to be more precise) that allows the creation of that specific service. This Factory abstraction can be defined on application level, and implemented inside the Composition Root.
For instance:
// Defined in application
public interface IForestFactory
{
IForest Create();
}
// Defined inside the Composition Root
public class ForestFactory : IForestFactory
{
private readonly Container container;
public ForestFactory(Container container) {
this.container = container;
}
public IForest Create() {
return this.container.GetInstance<IForest>();
}
}
// Inside the Bootstrapper
var factory = new ForestFactory(Container);
Container.Register<IForestFactory>(() => factory);
The second edition of the book however describes that these kinds of factories are often a code smell. Instead of using a factory, it is typically better to use a Virtual Proxy.
A Virtual Proxy is a stand-in for an object that should be created lazily. A Virtual Proxy however implements the same Abstraction as the lazily created object. This allows the Virtual Proxy to be injected into a consumer, without the consumer having to know of the existence of the Virtual Proxy.
In your case that means that you create a Virtual Proxy for IForest, for instance:
// Defined inside the Composition Root
public class LazyForestProxy : IForest
{
private readonly Container container;
public LazyForestProxy(Container container){
this.container = container;
}
// Implement IForest members
void IForest.Run() {
var forest = GetInstance();
// Forward the call to the 'real' forest
forest.Run();
}
private IForest GetInstance() {
return this.container.GetInstance<IForest>();
}
}
Is there anyway to get the hostcontrol / parentcontrol from a region in PRISM C# WPF. Im trying to write an custom region behaviour that modifies the hostcontrol if there is no views in the region.
There is a HostControl property in RegionBehavior class but it is alwasy null. How do i set it ? or how to get the hostcontrol.
Thanks for advice!
[Export(typeof(CollapseRegionBehavior))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class CollapseRegionBehavior : RegionBehavior, IHostAwareRegionBehavior
{
public DependencyObject HostControl { get; set; }
protected override void OnAttach()
{
if (this.Region.ActiveViews.Count() == 0)
{
}
}
}
Are you adding the RegionBehavior manually or do you register it in the bootstrapper in ConfigureDefaultRegionBehaviors?
It seems that if you add a behavior manually like this:
IRegion region = regionManager.Regions["MyRegion"];
region.Behaviors.Add("MyBehaviorKey", new MyBehavior());
the IHostAwareRegionBehavior interface has no effect. If you look at the PRISM source code in RegionBehaviorCollection.cs (Prism.Dektop.Regions) you'll clearly see that the Add method does not do anything related to the IHostAwareRegionBehavior interface.
However in RegionAdapterBase.cs, the interface is checked for in AttachDefaultBehaviors.
I ended up registering my RegionBehavior in the bootstrapper and checking the region name to see if there is work to be performed. Not very clean, but it works.
I'm trying to remove a Service Locator from an abstract base class, but I'm not sure what to replace it with. Here is a psuedo-example of what I've got:
public abstract class MyController : Controller
{
protected IKernel kernel;
public MyController(IKernel kernel) { this.kernel = kernel); }
protected void DoActions(Type[] types)
{
MySpecialResolver resolver = new MySpecialResolver(kernel);
foreach(var type in types)
{
IMyServiceInterface instance = resolver.Get(type);
instance.DoAction();
}
}
}
The problem with this is that the instanciator of a derived class doesn't know what bindings the kernel must have in order to keep MySpecialResolver from throwing an exception.
This might be intrinsicly intractable because I don't know from here which types I'll have to resolve. The derived classes are responsible for creating the types parameter, but they aren't hardcoded anywhere. (The types are based on the presence of attributes deep within the derived class's composition hierarchy.)
I've trying to fix this with lazy loading delegates, but so far I haven't come up with a clean solution.
Update
There are really two issues here, one is that the IoC container is passed to the controller, acting as a service locator. This is easy to remove--you can move the location up or down the call stack using all sorts of techniques.
The second issue is the difficult one, how can you ensure that the controller has the necessary services when the requirements aren't exposed until runtime. It should have been obvious from the start: you can't! You will always be dependent upon either the state of the service locator or contents of a collection. In this particular case no amount of fiddling will ever resolve the problem described in this article with staticly typed dependencies. I think that what I'm going to end up doing is passing a Lazy array into the controller constructor and throwing an exception if a required dependency is missing.
I agree with #chrisichris and #Mark Seemann.
Ditch the kernel from the controller. I'd switch your resolver composition a little bit so that your controller can remove the dependency on the IoC container and allow the resolver to be the only item that worries about the IoC container.
Then I would let the resolver get passed into the constructor of the controller. This will allow your controller to be far more testable.
For example:
public interface IMyServiceResolver
{
List<IMyServiceInterface> Resolve(Type[] types);
}
public class NinjectMyServiceResolver : IMyServiceResolver
{
private IKernal container = null;
public NinjectMyServiceResolver(IKernal container)
{
this.container = container;
}
public List<IMyServiceInterface> Resolve(Type[] types)
{
List<IMyServiceInterface> services = new List<IMyServiceInterface>();
foreach(var type in types)
{
IMyServiceInterface instance = container.Get(type);
services.Add(instance);
}
return services;
}
}
public abstract class MyController : Controller
{
private IMyServiceResolver resolver = null;
public MyController(IMyServiceResolver resolver)
{
this.resolver = resolver;
}
protected void DoActions(Type[] types)
{
var services = resolver.Resolve(types);
foreach(var service in services)
{
service.DoAction();
}
}
}
Now your controller isn't coupled to a specific IoC container. Also your controller is much more testable since you can mock the resolvers and not require an IoC container at all for your tests.
Alternatively, if you don't get to control when a controller is instantiated, you can modify it slightly:
public abstract class MyController : Controller
{
private static IMyServiceResolver resolver = null;
public static InitializeResolver(IMyServiceResolver resolver)
{
MyController.resolver = resolver;
}
public MyController()
{
// Now we support a default constructor
// since maybe someone else is instantiating this type
// that we don't control.
}
protected void DoActions(Type[] types)
{
var services = resolver.Resolve(types);
foreach(var service in services)
{
service.DoAction();
}
}
}
You would then call this at your application start up to initialize the resolver:
MyController.InitializeResolver(new NinjectMyServiceResolver(kernal));
We did this to handle elements created in XAML who require dependencies resolved but we wanted to remove Service Locator like requests.
Please excuse any syntactical errors :)
I'm writing a blog post series on the topic of refactoring an MVVM application with Service Locator calls in the view models you might find interesting. Part 2 is coming soon :)
http://kellabyte.com/2011/07/24/refactoring-to-improve-maintainability-and-blendability-using-ioc-part-1-view-models/
Maybe you should just do away the Kernel, Types and MySpecialResolver and let the subclasses call DoActions with the IMyServiceInterface instances they need as argument directly. And let the subclasses decide how they get to these instances - they should know best (or in case they don't know which exactly the one who ever decides which instances of IMyServiceInterface are needed)
I would have liked to have a bit more information before posting this answer, but Kelly put me on the spot. :) Telling me to put my code where my mouth is, so to speak.
Like I said in my comment to Kelly, I disagree with moving the resolver/locator from a static implementation to an injected implementation. I agree with ChrisChris that the dependencies the derived type needs should be resolved in that class and not delegated to the base class.
That said, here is how I would remove the service location...
Create Command Interface
First of all I would create a command interface for the specific implementation. In this case the types sent with the DoActions method are generated from attributes, so I would create an IAttributeCommand. I am adding a Matches method to the command in order to declare the command for use by certain types.
public interface IAttributeCommand
{
bool Matches(Type type);
void Execute();
}
Add Command Implementations
To implement the interface, I pass in the specific dependencies I need to execute my command (to be resolved by my container). I add a predicate to my Matches method, and define my Execute behavior.
public class MyTypeAttributeCommand : IAttributeCommand
{
MyDependency dependency;
SomeOtherDependency otherDependency;
public MyTypeAttributeCommand (MyDependency dependency, ISomeOtherDependency otherDependency)
{
this.dependency = dependency;
this.otherDependency = otherDependency
}
public bool Matches(Type type)
{
return type==typeof(MyType)
}
public void Execute()
{
// do action using dependency/dependencies
}
}
Register Commands with Container
In StructureMap (use your favorite container), I would register the array like so:
Scan(s=>
{
s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IAttributeCommand>();
s.WithDefaultConventions();
}
Select and Execute Commands Based on Type
Finally, on the base class, I define an IAttributeCommand array in my constructor arguments to be injected by the IOC container. When the derived type passes in the types array, I will execute the correct command based on the predicate.
public abstract class MyController : Controller
{
protected IAttributeCommand[] commands;
public MyController(IAttributeCommand[] commands) { this.commands = commands); }
protected void DoActions(Type[] types)
{
foreach(var type in types)
{
var command = commands.FirstOrDefault(x=>x.Matches(type));
if (command==null) continue;
command.Execute();
}
}
}
If you multiple commands can handle one type, you can change the implementation: commands.Where(x=>x.Matches(type)).ToList().ForEach(Execute);
The effect is the same, but there is a subtle difference in how the class is constructed. The class has no coupling to an IOC container and there is no service location. The implementation is more testable as the class can be constructed with its real dependencies, with no need to wire up a container/resolver.
here's my situation:
I have an application that generates stuff based on templates (using T4) and i have multiple templates class that inherit from an ITemplate interface.
What i wanna do in my Main is to dinamically inject some ITemplate implementations in my Generator class, what implementation to use being read from a, let's say, configuration file. Then in the Main i should call the Generator that will understand what template to use and call the proper TransformText().
I'm using Ninject.
It's the first time i use Dependency Injection in a statically typed language, so I'm not sure on how to proceed...
Regards,
Hugo
If you are truly want to use DI here a simple example, but if you are searching something like plugin system you might wanna check out mef.
Lets assume you have a generator
public class Generator
{
private ITemplate _template;
public Generator(ITemplate t)
{
_template = t;
}
public void Generate()
{
_template.Generate();
}
}
Setup your Modules.
public class MyNinjectModules : NinjectModule
{
public override void Load()
{
Bind<ITemplate>().To< TemplateImplementation>();
Bind<Generator>().ToSelf();
}
}
then prepare your Ninject Kernel, and use it.
public class Program
{
public static void Main(
{
var kernel = new StandardKernel(MyNinjectModules);
var myGenerator = kernel.Get<Generator>();
}
}
public class StatisticsViewPresenter
{
private IStatisticsView view;
private Statistics statsModel;
public StatisticsViewPresenter(IStatisticsView view, Statistics statsModel)
{
this.view = view;
this.statsModel = statsModel;
}
}
I don't use events (but am willing to if it can solve my problem), so my View classes look like this:
public class StatisticsForm : Form, IStatisticsView
{
public StatisticsForm()
{
InitializeComponent();
}
[Inject]
public StatisticsViewPresenter Presenter
{
private get;
set;
}
}
With
kernel.Bind<StatisticsPresenter>().ToSelf().InSingletonScope();
kernel.Bind<IStatisticsView>().To<StatisticsForm>();
kernel.Get<IStatisticsView>();
it builds up the Form, builds up the presenter, then injects the presenter into the Presenter property. Everything's peachy. (Except for that singleton-scoped presenter--any thoughts on a better way to do that? Perhaps just manually inject the presenter into the view's Presenter property inside the presenter's constructor: this.view.Presenter = this).
But if I turn StatisticsForm into StatisticsUserControl and drag-drop it onto my MainForm, it's not being injected into MainForm by Ninject, it's simply being new'd by the Designer. I see three solutions here:
1) Don't use UserControls and just use one giant form that implements these multiple views (eww);
2) Inject UserControls into my form and lose Designer support;
3) Your solution! :)
My approach to use Ninject with forms, usercontrols and the designer is:
Use factories to create the forms (also for the usercontrols if you create some controls dinamically)
for the usercontrols and the forms keep the constructors without parameters and use property injection
add an Activation strategy to the kernel that check if ninject has just created a form or a usercontrol. If that is the case, the activation strategy iterates over the controls in the Controls property of the UserControl (or the Form) and calls Kernel.Inject(UserControl) for each usercontrol. (An Activation strategy is some code ninject executes after it has injected an object)
You can use the designer and have forms and usercontrols with dependencies injected via Ninject.
The only drawback is that you have to use property injection instead of constructor injection for the usercontrols (and the forms)
namespace Majiic.Ninject
{
public class WindowsFormsStrategy : ActivationStrategy
{
// Activate is called after Kernel.Inject
//even for objects not created by Ninject
//To avoid multiple "injections" in the same nested controls
//we put this flag to false.
private bool _activatingControls = false;
public override void Activate(IContext context, InstanceReference reference)
{
reference.IfInstanceIs<UserControl>(uc =>
{
if (!_activatingControls)
{
Trace.TraceInformation("Activate. Injecting dependencies in User control of type {0}", uc.GetType());
_activatingControls = true;
context.Kernel.InjectDescendantOf(uc);
_activatingControls = false;
}
});
reference.IfInstanceIs<Form>(form =>
{
if (!_activatingControls)
{
Trace.TraceInformation("Activate. Injecting dependencies in Form of type {0}", form.GetType());
_activatingControls = true;
context.Kernel.InjectDescendantOf(form);
_activatingControls = false;
}
});
}
}
}
Create the kernel and add the Activation Strategy
var kernel=new StandardKernel(new CommonMajiicNinjectModule());
kernel.Components.Add<IActivationStrategy, WindowsFormsStrategy>();
kernel extensions to iterate over descendents controls
namespace Majiic.Ninject
{
static public class WinFormsInstanceProviderAux
{
static public void InjectDescendantOf(this IKernel kernel, ContainerControl containerControl)
{
var childrenControls = containerControl.Controls.Cast<Control>();
foreach (var control in childrenControls )
{
InjectUserControlsOf(kernel, control);
}
}
static private void InjectUserControlsOf(this IKernel kernel, Control control)
{
//only user controls can have properties defined as n-inject-able
if (control is UserControl)
{
Trace.TraceInformation("Injecting dependencies in User Control of type {0}", control.GetType());
kernel.Inject(control);
}
//A non user control can have children that are user controls and should be n-injected
var childrenControls = control.Controls.Cast<Control>();
foreach (var childControl in childrenControls )
{
InjectUserControlsOf(kernel, childControl );
}
}
}
}
This is certainly an interesting area of, should I say, research. We've made ourselves a solution where we host user controls in a generic form.
Our generic form is not intended for use with the Designer. Through code we add the chosen user control to the Form dynamically.
For other frameworks you should look at Prism/Composite from the Microsoft Patterns & Practices group. Here's an article discussing extensions for WinForms.
I recently created some reuseable UserControls with the need of Dependencies to inject. As the IoC Container isn't used to create those UserControls, obviously he cannot automatically inject the Dependencies.
My Solution is, a Base-Class to enable at least Property Injection. Constructor Injection is not supported, as a parameterless Constructor is used to create those instances.
public class NinjectUserControl : UserControl
{
// Generally this is considered to be a bad practice,
//however I didn't find any better way. If you do, please share :)
public static IKernel Kernel { private get; set; }
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
RequestActivation(Kernel);
}
protected virtual void RequestActivation(IKernel kernel)
{
kernel?.Inject(this);
}
}
To get it to Work you need to set the Kernel once. Typically this is somewhere inside your program.cs (WinForms) or App.xaml.cs (WPF)
IocKernel = new StandardKernel(); // typically a static member
NinjectUserControl.Kernel = IocKernel;
IocKernel.Load(new Module()); // loading modules
// .. Create MainForm or whatever
To use, simply inherit NinjectUserControl and then let the Kernel Inject your dependencies via Property Injection:
[Inject]
public IService Service { private get; set; }
please note, that those dependencies are not accessible inside the Constructor.