Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I have tried this myself, and unfortunately I can't seem to get it to work properly. I do the following in my solution:</p> <pre><code>public class WindsorViewPageActivator : IViewPageActivator { private readonly IKernel _kernel; /// &lt;summary&gt; /// Initializes a new instance of the &lt;see cref="WindsorViewPageActivator"/&gt; class. /// &lt;/summary&gt; /// &lt;param name="kernel"&gt;The kernel.&lt;/param&gt; public WindsorViewPageActivator([NotNull] IKernel kernel) { if (kernel == null) throw new ArgumentNullException("kernel"); _kernel = kernel; } public object Create(ControllerContext controllerContext, Type type) { if (!_kernel.HasComponent(type)) { if (IsSupportedView(type)) { _kernel.Register(Component.For(type).LifestylePerWebRequest()); } else { return Activator.CreateInstance(type); } } var viewPageInstance = _kernel.Resolve(type); return viewPageInstance; } /// &lt;summary&gt; /// Determines whether the specified type is of a supported view type. /// &lt;/summary&gt; /// &lt;param name="viewType"&gt;Type of the service.&lt;/param&gt; /// &lt;returns&gt; /// &lt;c&gt;true&lt;/c&gt; if the specified type is of a supported view type; otherwise, &lt;c&gt;false&lt;/c&gt;. /// &lt;/returns&gt; private static bool IsSupportedView(Type viewType) { return viewType.IsAssignableTo&lt;WebViewPage&gt;() || viewType.IsAssignableTo&lt;ViewPage&gt;() || viewType.IsAssignableTo&lt;ViewMasterPage&gt;() || viewType.IsAssignableTo&lt;ViewUserControl&gt;() ; } } </code></pre> <p>This works as long as you don't change anything in your markup. If you do, you'll get a registration error, as the view now will generate a new type, that doesn't exist in the container (but it has the same name!). What I thought of doing, was to aggressively release the view component as soon as it's resolved, but I can't get rid of it in the container for some reason. Not even an explicit call to <code>_kernel.ReleaseComponent(viewPageInstance)</code> would do it (but that's of course just releasing the instance, not the type).</p> <p>What we really need to do, is make Windsor inject properties into existing instances. That is, use <code>Activator.CreateInstance(type)</code> and then tell Windsor to inject the properties into the instance. But Windsor doesn't support injecting properties into existing instances, so we need to hack something together, that will do that for us. I've seen this one <a href="http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/" rel="nofollow">http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/</a> (at the bottom), but that wouldn't perform very well.</p> <p>My solution was simply to manually set my properties in the viewpage activator (you have a base viewpage type), but maybe there's some better solution?</p> <p><strong>EDIT</strong></p> <p>I managed to get it working after all!</p> <p>My solution is to simply create a custom component activator and mimic what's being done in the MVC framework, like so:</p> <pre><code>public class ViewPageComponentActivator : DefaultComponentActivator { public ViewPageComponentActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction) : base(model, kernel, onCreation, onDestruction) { } protected override object CreateInstance(CreationContext context, ConstructorCandidate constructor, object[] arguments) { // Do like the MVC framework. var instance = Activator.CreateInstance(context.RequestedType); return instance; } } </code></pre> <p>The component activator simply always return a new instance of the view. Because the component is registered as being transient, <code>CreateInstance</code>is always called. There might be some tweaking possibilities here.</p> <p>The viewpage activator is now much simpler. Note that the type of service is different whenever you change the view, so we must register the type based on it's unique name (I haven't tweaked this yet, but there might be a nicer way to name the component).</p> <pre><code>/// &lt;summary&gt; /// An activator using Castle Kernel for activating views. /// &lt;/summary&gt; public class WindsorViewPageActivator : IViewPageActivator { private readonly IKernel _kernel; /// &lt;summary&gt; /// Initializes a new instance of the &lt;see cref="WindsorViewPageActivator"/&gt; class. /// &lt;/summary&gt; /// &lt;param name="kernel"&gt;The kernel.&lt;/param&gt; public WindsorViewPageActivator([NotNull] IKernel kernel) { if (kernel == null) throw new ArgumentNullException("kernel"); _kernel = kernel; } public object Create(ControllerContext controllerContext, Type type) { if (!_kernel.HasComponent(type.FullName)) { _kernel.Register(Component.For(type).Named(type.FullName).Activator&lt;ViewPageComponentActivator&gt;().LifestyleTransient()); } return _kernel.Resolve(type.FullName, type); } } </code></pre> <p>I hope this might be of use to someone in similar situations.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload