容器无法解析单个接口

时间:2013-11-22 15:55:49

标签: c# entity-framework asp.net-mvc-4 castle-windsor

我有一个公共站点控制器,我的所有控制器都来自我的MVC网站。我已将公共服务类放在那里的所有视图/控制器中。

public class SiteController : Controller {
        #region Properties
        public IGlobalService GlobalService { get; set; }
        public IMenuService MenuService { get; set; }
        public IClientService ClientService { get; set; }
        public ICertificateService CertificateService { get; set; }
        #endregion

        protected override void OnActionExecuting( ActionExecutingContext filterContext ) {
            ViewBag.ErrorEmail = GlobalService.ErrorEmail;
            ViewBag.Company = GlobalService.Company;
            ViewBag.TopLevel = MenuService.GetTopLevel();

            base.OnActionExecuting( filterContext );
        }

最近,我开始实现一个动态菜单,并为Menu partial实现了一个ChildActionOnly方法

[ChildActionOnly]
public ActionResult Menu() {
    var items = MenuService.GetTopLevel();
    if( items == null || items.Count > 0 )
        throw new NullReferenceException("Menu must have at least 1 top-level Menu Item!");

    var topmenu = new Menu();
    foreach( var item in items ) {
        topmenu.Items.Add( new MenuItem( item.MenuId ){
            MenuItemName = item.Key,
            MenuItemPath = item.Value
        });
    }

    return PartialView("_Menu", topmenu);
}

直到我实现了ChildActionOnly方法,理论上正在注入MenuService对象。我无法验证这一点,因为在我开始调试ViewBag.TopLevel = MenuService.GetTopLevel();之前它没有被使用。

话虽如此,当我将断点放在ViewBag.TopLevel的行上时,我可以检查与Controller关联的4个Service属性中的3个。如上所述,MenuService属性是唯一未初始化的属性。

这是我的WindsorContainer初始化程序:

public static void Initialize(string log4netPath) {
    var container = new WindsorContainer();
    container.Kernel.ComponentModelCreated += ( s => {
        if( s.LifestyleType == LifestyleType.Undefined )
            s.LifestyleType = LifestyleType.PerWebRequest;
    } );

    container.Install(
        new DomainInstaller(),
        new RepositoryInstaller() ,
        new ServiceInstaller() ,
        FromAssembly.This()
    );
    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory( container.Kernel ) );

    container.AddFacility( new LoggingFacility( LoggerImplementation.Log4net , log4netPath ) );

    CWC.Init( container );
}

ServiceInstaller声明:

public class ServiceInstaller : IWindsorInstaller {
    #region IWindsorInstaller Members

    public void Install( Castle.Windsor.IWindsorContainer container , Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store ) {
        container.Register( Types.FromAssembly( Assembly.GetExecutingAssembly() )
            .Where( t => t.Namespace.StartsWith( "Woodsoft.Service" ) )
            .WithService.FirstInterface().LifestylePerWebRequest() );
    }

    #endregion
}

MenuService声明:

public interface IMenuService {
    ICollection<Menu> GetTopLevel();
    ICollection<Menu> GetChildren( int id );
}
public class MenuService : IMenuService {
    public IMenuRepository MenuRepository { get; set; }

    public MenuService() { }

    public ICollection<Menu> GetTopLevel() {
        return MenuRepository.FindAll()
            .Where( m => ( m.ParentId == null || m.ParentId == 0 ) )
            .ToList();
    }

    public ICollection<Menu> GetChildren( int id ) {
        return MenuRepository.FindChildren( id );
    }
}

也许有一些我缺少的东西,但是如果4个Service对象中的3个正在初始化并且在调试时可以访问,那么会发生什么会导致1个Service对象没有初始化,并且通过代理不可用。

为了比较,这里是GlobalService对象:

public interface IGlobalService {
    string this[ string key ] { get; set; }
    string AdminEmail { get; set; }
    string BCCEmail { get; set; }
    string ErrorEmail { get; set; }
    string Domain { get; set; }
    string Company { get; set; }
}

public class GlobalService : IGlobalService {
    public IGlobalRepository GlobalRepository { get; set; }

    public GlobalService() { }

    #region Getter/Setter methods
    public string GetValue( string key ) {
        return GlobalRepository.FindByKey( key ).Value;
    }
    private void SetValue( string key , string value ) {
        var global = GlobalRepository.FindByKey( key );
        global.Value = value;
        GlobalRepository.Save();
    }

    #endregion

    #region IGlobalService Members

    public string this[ string key ] {
        get { return GetValue( key ); }
        set { SetValue( key , value ); }
    }

    public string AdminEmail {
        get { return this[ "admin_email" ].ToEmail( Domain ); }
        set { this[ "admin_email" ] = value; }
    }

    public string BCCEmail {
        get { return this[ "bcc_email" ].ToEmail( Domain ); }
        set { this[ "bcc_email" ] = value; }
    }

    public string ErrorEmail {
        get { return this[ "error_email" ].ToEmail( Domain ); }
        set { this[ "error_email" ] = value; }
    }

    public string Domain {
        get { return this[ "domain" ]; }
        set { this[ "domain" ] = value; }
    }

    public string Company {
        get { return this[ "company" ]; }
        set { this[ "company" ] = value; }
    }
    #endregion


}

更新时间:2013-11-22 @ 10:59

我将它从IMenuService更改为IMenuRepository并且它加载了接口就好了。

虽然MenuService内部的某些属性/方法存在潜在问题,但似乎没有。

更新2013-11-25

以下是WindsorControllerFactory

public class WindsorControllerFactory : DefaultControllerFactory {
    private readonly IKernel Kernel;

    public WindsorControllerFactory( IKernel kernel ) {
        Kernel = kernel;
    }

    public override void ReleaseController( IController controller ) {
        Kernel.ReleaseComponent( controller );
    }

    protected override IController GetControllerInstance( System.Web.Routing.RequestContext requestContext , Type controllerType ) {
        if( controllerType == null ) 
            throw new HttpException( 404 , string.Format( "The controller for path '{0}' could not be found." , requestContext.HttpContext.Request.Path ) );

        return ( IController ) Kernel.Resolve( controllerType );
    }
}

0 个答案:

没有答案