2

I ran Code Analysis on my Web API project, in which I'm trying to implement IoC and DI using Castle Windsor, and it found four problems. The four things it found were all in WindsorDependencyResolver, and all four are "Implement IDisposable correctly" namely:

0) CA1063 Implement IDisposable correctly Provide an overridable implementation of Dispose(bool) on 'WindsorDependencyResolver' or mark the type as sealed. A call to Dispose(false) should only clean up native resources. A call to Dispose(true) should clean up both managed and native resources.

That points to this line of code:

public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver

1) CA1063 Implement IDisposable correctly Modify 'WindsorDependencyResolver.Dispose()' so that it calls Dispose(true), then calls GC.SuppressFinalize on the current object instance ('this' or 'Me' in Visual Basic), and then returns.

That points to this line of code:

public void Dispose()

2) Same as O, but for the WindsorDependencyScope : IDependencyScope class.

3) Same as 1, but ""

I got the code I'm trying from Castle Windsor articles online, mainly from from this post. The entire code for this file is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using System.Web.Http;
using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.SubSystems.Configuration;
using HandheldServer.Models;
namespace HandheldServer
{
 public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
 {
 private readonly IWindsorContainer _container;
 public WindsorDependencyResolver(IWindsorContainer container)
 {
 _container = container;
 }
 public IDependencyScope BeginScope()
 {
 return new WindsorDependencyScope(_container);
 }
 public object GetService(Type serviceType)
 {
 return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
 }
 public IEnumerable<object> GetServices(Type serviceType)
 {
 if (!_container.Kernel.HasComponent(serviceType))
 {
 return new object[0];
 }
 return _container.ResolveAll(serviceType).Cast<object>();
 }
 public void Dispose()
 {
 _container.Dispose();
 }
 }
 public class WindsorDependencyScope : IDependencyScope
 {
 private readonly IWindsorContainer _container;
 private readonly IDisposable _scope;
 public WindsorDependencyScope(IWindsorContainer container)
 {
 this._container = container;
 this._scope = container.BeginScope(); 
 }
 public object GetService(Type serviceType)
 {
 if (_container.Kernel.HasComponent(serviceType))
 {
 return _container.Resolve(serviceType);
 }
 else
 {
 return null;
 }
 }
 public IEnumerable<object> GetServices(Type serviceType)
 {
 return this._container.ResolveAll(serviceType).Cast<object>();
 }
 public void Dispose()
 {
 this._scope.Dispose();
 }
 }
 public class ApiControllersInstaller : IWindsorInstaller
 {
 public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
 {
 container.Register(Classes.FromThisAssembly() // should it be Types instead of Classes?
 .BasedOn<ApiController>()
 .LifestylePerWebRequest());
 }
 }
 // This idea from https://github.com/argeset/set-locale/blob/master/src/client/SetLocale.Client.Web/Configurations/IocConfig.cs
 public class ServiceInstaller : IWindsorInstaller
 {
 public void Install(IWindsorContainer container, IConfigurationStore store)
 {
 container.Register(
 Component.For<IDeliveryItemRepository>().ImplementedBy<DeliveryItemRepository>().LifestylePerWebRequest(),
 Component.For<IDeliveryRepository>().ImplementedBy<DeliveryRepository>().LifestylePerWebRequest(),
 Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest(),
 Component.For<IExpenseRepository>().ImplementedBy<ExpenseRepository>().LifestylePerWebRequest(),
 Component.For<IInventoryItemRepository>().ImplementedBy<InventoryItemRepository>().LifestylePerWebRequest(),
 Component.For<IInventoryRepository>().ImplementedBy<InventoryRepository>().LifestylePerWebRequest(),
 Component.For<IItemGroupRepository>().ImplementedBy<ItemGroupRepository>().LifestylePerWebRequest());
 }
 }
}

What is the best way to mollify the Code Analysis tool?

asked Jan 9, 2014 at 0:07
3
  • 2
    Turn warnings off? You don't control the Windsor code, unless you decide to fork it; you may have to decide if accepting the tool you've chosen, in spite of the warnings, is an acceptable risk to you. Commented Jan 9, 2014 at 0:08
  • So you're saying those things Code Analysis caught are not important? Actually, I thought it was my code that was the problem - I'm not doing it right, probably... Commented Jan 9, 2014 at 0:12
  • 2
    The sample code you referred to is calling this._scope.Dispose(); I think you're going to have to live with the warnings. Commented Jan 9, 2014 at 0:45

1 Answer 1

3

Before answering your question please note that you should be very careful calling Dispose() on an object you didn't create and therefore are probably not responsible for. By this I mean the line

_container.Dispose();

the container was passed in so strictly speaking it is not yours to dispose of.

The easiest way to mollify the Code Analysis tool is to implement IDisposable as recommended

public class WindsorDependencyResolver
{
 public WindsorDependencyResolver()
 {
 }
 public void Dispose()
 {
 Dispose(true);
 GC.SuppressFinalize(this);
 }
 private bool disposed;
 protected virtual void Dispose(bool disposing)
 {
 if (this.disposed) return;
 if (disposing)
 {
 // call dispose on managed resources
 // set to null
 }
 this.disposed = true;
 }
}

See here for a thorough explanation of why, followed by many reasoned arguments as to why not! I would suggest that at the end of the day you should stick to your chosen standards and if that includes the code analysis tool then so be it.

Steven
174k25 gold badges355 silver badges453 bronze badges
answered Jan 9, 2014 at 21:41
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.