Castle IoC未在服务器上注册服务类

时间:2014-08-25 16:41:20

标签: .net castle-windsor

部署到我的服务器时,我的asp.net mvc Web应用程序出现了问题,但是当我通过visual studio运行时却没有。

这是错误

无法创建组件' IndustrialRealEstate.Web.Controllers.ZoningController'因为它有依赖性来满足。'

有问题的依赖是一个名为ZoningService的服务,它基于一个名为IDataService的通用接口。

以下是我正在使用的代码

控制器:

public class ZoningController : BaseController
{
    private readonly IDataService<ZoningWrapper> _zoningService;

    public ZoningController(IDataService<ZoningWrapper> service)
    {
        _zoningService = service;
    }
//functions
}

HasContext抽象类:

public abstract class HasContext
{
    private IREDbContext _ireDbContext;

    public IREDbContext IREDbContext
    {
        get
        {
            if (_ireDbContext != null)
                return _ireDbContext;

            _ireDbContext = new IREDbContext();
            return _ireDbContext;
        }
    }
}

IDataService接口

public interface IDataService<T>
{
    T Get(string id);
    ICollection<T> GetAll();
    T Save(T dataWrapper);
    bool AlreadyExists(T dataWrapper);
    bool HasDependency(string id);
    bool Delete(string id);
}

服务:

public class ZoningService : HasContext, IDataService<ZoningWrapper>
{
//Implemented functions from the interface
}

的ServiceInstaller:

public class ServicesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<IDataService<ZoningWrapper>>().ImplementedBy<ZoningService>());
    }
}

现在,正如我所说,当我通过视觉工作室运行时,它正在100%运行。直到我部署到服务器并且数据没有通过,我才意识到存在问题。阅读日志给出了这个特定的信息,我无法确定问题所在。

如果有任何人有任何见解或方向,他们可以指出我,我会非常感激。

编辑 - 以下是控制器的连接方式

    public class ControllersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Castle.MicroKernel.Registration.Classes.FromThisAssembly()
            .BasedOn<BaseController>()
            .LifestylePerWebRequest()
            .Configure(x => x.Named(x.Implementation.FullName)));
        container.Register(Castle.MicroKernel.Registration.Classes.FromThisAssembly()
            .BasedOn<Controller>()
            .LifestylePerWebRequest()
            .Configure(x => x.Named(x.Implementation.FullName)));
    }
}

2 个答案:

答案 0 :(得分:0)

做了类似于WebAPI项目的事情。需要添加以下内容..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Dependencies;
using Castle.MicroKernel;
using Castle.MicroKernel.Lifestyle;

namespace MyProject.DependencyInjection
{
    public class WindsorDependencyScope : IDependencyScope
    {
        private readonly IKernel container;
        private readonly IDisposable scope;

        public WindsorDependencyScope(IKernel container)
        {
            this.container = container;
            this.scope = container.BeginScope();
        }

        public object GetService(Type serviceType)
        {
            return this.container.HasComponent(serviceType) ? this.container.Resolve(serviceType) : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this.container.ResolveAll(serviceType).Cast<object>();
        }

        public void Dispose()
        {
            this.scope.Dispose();
        }
    }
}

...然后添加......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Dependencies;
using Castle.MicroKernel;

namespace MyProject.DependencyInjection
{
    internal class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
    {
        private readonly IKernel container;

        public WindsorDependencyResolver(IKernel container)
        {
            this.container = container;
        }

        public IDependencyScope BeginScope()
        {
            return new WindsorDependencyScope(this.container);
        }

        public object GetService(Type serviceType)
        {
            return this.container.HasComponent(serviceType) ? this.container.Resolve(serviceType) : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this.container.ResolveAll(serviceType).Cast<object>();
        }

        public void Dispose() { }
    }
}

然后修改global.asax文件......

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.Windsor;
using Castle.Windsor.Installer;
using MyProject.DependencyInjection;

namespace MyProject
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            var container = new WindsorContainer();
            container.Install(FromAssembly.This());
            GlobalConfiguration.Configuration.DependencyResolver = new WindsorDependencyResolver(container.Kernel);

            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

我的安装程序示例......

using System.Web.Http;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;

namespace MyProject.DependencyInjection
{
    public class WindsorWebApiInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Types.FromThisAssembly().BasedOn<ApiController>().LifestyleScoped()
                , Component.For<MyProject.Database.IDataAccessMethods>().ImplementedBy<MyProject.Database.DataAccessMethods>().LifestylePerWebRequest()
            );
        }
    }
}

答案 1 :(得分:0)

我会检查您的安装程序是否都在同一个程序集中,并检查container.Install调用是否与您需要涵盖的程序集范围相匹配。例如,初始化程序时,可能无法加载包含服务安装程序的程序集。也许记录安装的内容可以帮助您检查代码是否在程序启动时运行。


Re:调试这类问题:

很难在服务器上确定您的容器缺少什么。如果您可以在可以进行调试的机器上重现问题,我建议您使用Castle Debugging views

在我看来,更好的是,您可以设置一个测试来检查Castle是否可以解决所有依赖项:

[SetUpFixture]
public class TestIOC
{
    public IWindsorContainer Target { get; set; }

    [SetUp()]
    public void before_all_tests()
    {
        Target = global::Main.Structure.IOC.Initialize();
    }

    public class GeneralTests : TestIOC
    {
        [Test()]
        public void should_never_have_a_potentially_misconfigured_component()
        {
            var host = (IDiagnosticsHost)Target.Kernel.GetSubSystem(SubSystemConstants.DiagnosticsKey);
            var diagnostics = host.GetDiagnostic<IPotentiallyMisconfiguredComponentsDiagnostic>();
            var misconfiguredHandlers = diagnostics.Inspect();

            if (misconfiguredHandlers.Any())
            {
                var message = new StringBuilder();
                var inspector = new DependencyInspector(message);
                foreach (IExposeDependencyInfo handler in misconfiguredHandlers)
                {
                    handler.ObtainDependencyDetails(inspector);
                }
                Console.WriteLine(message.ToString());
            }

            Assert.AreEqual(0, misconfiguredHandlers.Count());
        }
    }
}

这直接来自我使用的测试套件:如果您的IOC设置无法解析某些元素,它将写入std输出。在NUnit中,这转化为一个失败的测试,其中包含一些缺失的细节。 global::Main.Structure.IOC.Initialize();调用在设置后返回容器,我也在主代码中使用它。

以下是诊断输出的示例,可帮助您找到缺少的配置:

  

* Main.Structure.TestIOC + GeneralTests.should_never_have_a_potentially_misconfigured_component

     

'Main.Configuration.NotificationManagementConfiguration'正在等待   以下依赖项:    - 未提供参数'daily_notification_time'。你忘了设置依赖吗?

您甚至可以在程序开始时将代码添加为健全性检查,并尽可能快地记录任何错误。