2

Я провел анализ кода в моем проекте веб-API, в котором я пытаюсь реализовать IoC и DI с помощью Castle Windsor, и он обнаружил четыре проблемы. Четыре вещи, он нашел, были все в WindsorDependencyResolver, и все четыре «правильно Реализовать IDisposable», а именно:Каким образом Dispose должен быть закодирован в классах, реализующих IDependencyResolver и IDependencyScope?

0) CA1063 Реализовать IDisposable правильно Обеспечить Overridable реализацию Dispose (BOOL) на «WindsorDependencyResolver» или отметьте тип, запечатаны. Вызов Dispose (false) должен только очищать собственные ресурсы. Вызов Dispose (true) должен очищать как управляемые, так и собственные ресурсы.

Это указывает на эту строку кода:

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

1) CA1063 Реализовать IDisposable правильно Изменить 'WindsorDependencyResolver.Dispose()' так, что он вызывает Dispose (истинное), затем вызывает GC.SuppressFinalize на текущий экземпляр объекта ('this' или 'Me' в Visual Basic), а затем возвращается.

Это указывает на эту строку кода:

public void Dispose() 

2) То же, что O, но и для WindsorDependencyScope: класс IDependencyScope.

3) То же, что 1, но «»

Я получил код, который я пытаюсь из статей Замок Виндзор онлайн, в основном из из this post. Весь код этого файла:

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()); 
     } 
    } 
} 

Каков наилучший способ смягчить инструмент анализа кода?

+2

Выключить предупреждения? Вы не контролируете код Виндзора, если только вы не решите его разветвить; вам может потребоваться решить, является ли принятие выбранного вами инструмента, несмотря на предупреждения, приемлемым для вас. –

+0

Значит, вы говорите те вещи, которые анализ кода не имеет значения? На самом деле, я думал, что это был мой код, который был проблемой - я не делаю это правильно, возможно ... –

+2

Образец кода, на который вы ссылались, вызывает 'this._scope.Dispose();' Я думаю, что вы собираетесь чтобы жить с предупреждениями. –

ответ

3

Прежде чем отвечать на ваш вопрос, учтите, что вы должны быть очень осторожны при вызове Dispose() на объект, который вы не создали, и поэтому, вероятно, не отвечаете. Под этим я имею в виду линию

_container.Dispose(); 

container был принят в так строго говоря, это не ваш распоряжаться.

Самый простой способ смягчить инструмент анализа кода заключается в реализации IDisposable как рекомендовано

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; 
    } 
} 

См here для подробного объяснения, почему, после многих аргументированных доводов, почему нет! Я бы предположил, что в конце дня вы должны придерживаться выбранных вами стандартов, и если это включает в себя инструмент анализа кода, то пусть будет так.