2

我在我的 Web API 项目上运行了代码分析,我在其中尝试使用 Castle Windsor 实现 IoC 和 DI,它发现了四个问题。它发现的四件事都在 WindsorDependencyResolver 中,并且所有四件事都是“正确实施 IDisposable”,即:

0) CA1063 正确实现 IDisposable 在“WindsorDependencyResolver”上提供可覆盖的 Dispose(bool) 实现或将类型标记为密封。对 Dispose(false) 的调用应该只清理本机资源。对 Dispose(true) 的调用应该清理托管资源和本机资源。

这指向这行代码:

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

1) CA1063 正确实现 IDisposable 修改“WindsorDependencyResolver.Dispose()”,使其调用 Dispose(true),然后对当前对象实例(Visual Basic 中的“this”或“Me”)调用 GC.SuppressFinalize,然后返回。

这指向这行代码:

public void Dispose()

2) 与 O 相同,但适用于 WindsorDependencyScope : IDependencyScope 类。

3) 与 1 相同,但 ""

我从 Castle Windsor 在线文章中获得了我正在尝试的代码,主要来自这篇文章。该文件的完整代码是:

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

缓和代码分析工具的最佳方法是什么?

4

1 回答 1

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

有关原因的详细解释,请参见此处,然后是关于为什么不这样做的许多合理论证!我建议在一天结束时你应该坚持你选择的标准,如果这包括代码分析工具,那就这样吧。

于 2014-01-09T21:41:42.463 回答