Как следует кодировать Dispose в классах, реализующих IDependencyResolver и IDependencyScope?
Вопрос
Я запустил анализ кода в своем проекте веб-API, в котором пытаюсь реализовать IoC и DI с помощью Castle Windsor, и обнаружил четыре проблемы.Все четыре вещи, которые он нашел, были в WindsorDependencyResolver, и все четыре являются «правильной реализацией IDisposable», а именно:
0) CA1063 Реализуйте Idisposable правильно обеспечивает переоценку реализации Dispose (Bool) на «WindSordEpendencyResolver» или отметьте тип как герметичный.Вызов Dispose(false) должен очищать только собственные ресурсы.Вызов Dispose(true) должен очистить как управляемые, так и собственные ресурсы.
Это указывает на эту строку кода:
public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
1) CA1063 Реализуйте Idisposable правильно изменить 'windsordependencyresolver.dispose ()', чтобы он вызовал (true (true), затем вызывает Gc.suppressfinalize на текущем экземпляре объекта («это» или «я» в Visual Basic), а затем возвращается.
Это указывает на эту строку кода:
public void Dispose()
2) То же, что и O, но для WindsorDependencyScope:Класс IDependencyScope.
3) То же, что 1, но ""
Я получил код, который пытаюсь использовать, из онлайн-статей о замке Виндзор, в основном из эта почта.Полный код этого файла:
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());
}
}
}
Как лучше всего смягчить инструмент анализа кода?
Решение
Прежде чем ответить на ваш вопрос, обратите внимание, что вам следует быть очень осторожными, звоня 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;
}
}
Видеть здесь за подробное объяснение, почему, с последующим множеством аргументированных аргументов, почему бы и нет!Я бы посоветовал вам, в конце концов, придерживаться выбранных вами стандартов, и если это включает в себя инструмент анализа кода, то пусть будет так.