0

我正在尝试使用 Castle Windsor 和依赖注入创建一个 ASP.NET MVC 项目。一切正常,期待以下内容:

全球.asax

Container = new WindsorContainer();
Container.Install(new WebInstaller(), new LoggingInstaller());

var customControllerFactory = new CustomControllerFactory(Container);
ControllerBuilder.Current.SetControllerFactory(customControllerFactory);

用于注册 Castle 类的 Webinstaller:

string connectionStr = GetConnectionString("MainModel");
container.Register(Component.For(typeof(MainModelContainer)).DependsOn(new { 
          connectionString = connectionStr }).LifestylePerWebRequest());
container.Register(Classes.FromAssemblyContaining<MemberQueries>().InNamespace("User.EF.Queries").WithService.DefaultInterfaces().LifestylePerWebRequest());
container.Register(Classes.FromAssemblyContaining<HomeController>().BasedOn<IController>().LifestylePerWebRequest());

//PROBLEM that doesn't work
container.Register(Classes.FromAssemblyContaining<HomeController>().BasedOn<IAddMessage>().LifestylePerWebRequest());

家庭控制器

public IAddMessage AddMessage { get; set; }
private readonly IMemberQueries _memberContract;

public HomeController(IMemberQueries memberContract)
{
  _memberContract = memberContract;
}

public ActionResult Index()
{
   //PROBLEM AddMessage is Null and is not resolved automaticaly
   AddMessage.Add("Test", MessageTypes.message);
   return View("Index");
}

IAddMessage 实现

public class CustomMessage : IAddMessage
{
    private IController Controller { get; set; }

    public CustomMessage(IController controller)
    {
        Controller = controller;
    }

    public void Add(string text, MessageTypes messageTypes)
    {
        //TODO
    }
}

IAddMessage 接口

public interface IAddMessage
{
    void Add(string text, MessageTypes messageTypes);
}

问题是,IAddMessage 属性为空,因为容器无法解析 CustomMessage 构造函数中的 IController 依赖项。但我不知道如何解决这个问题。

Castle 容器中的内部错误消息显示:

此组件的某些依赖项无法静态解析。'User.Web.UI.Helper.Messages.CustomMessage' 正在等待以下依赖项: - 未注册的服务'System.Web.Mvc.IController'。

我在网上看了很多,但我找不到任何工作提示或解决我的问题的方法。

4

2 回答 2

1

问题是您还没有注册 IController 依赖项。我想您认为您是通过以下行做到的:

container.Register(Classes.FromAssemblyContaining<HomeController>().BasedOn<IController>().LifestylePerWebRequest());

这看起来好像您正在这样做,但您实际上正在做的是注册所有实现此接口的类。因此,当您向容器请求 aHomeController时,它会知道如何解决该问题,但是,如果您向它请求 IController,它将不知道是创建 aHomeController还是其他任何控制器。

您可能想要的是当前的活动控制器。为此,您可能必须从 CustomControllerFactory 继承并将创建的控制器保存在请求范围内。然后,您可以从 CustomMessage 类中的请求范围中检索它。

您可以检查以下线程以了解如何执行此操作:Asp.net mvc 3- get the current controller instance (not just name)

于 2013-08-30T23:53:51.710 回答
0

在 Kenneth 的帮助下,我找到了如下所示的解决方案:

private const string CurrentControllerIndexName = "CurrentControllerItem";

protected override IController GetControllerInstance(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));
        }

        var controller = (IController)this._container.Resolve(controllerType);
        //I am Using the Context not the current Session!
        if(HttpContext.Current.Items.Contains(CurrentControllerIndexName))
        {
            HttpContext.Current.Items.Remove(CurrentControllerIndexName);
        }

        HttpContext.Current.Items.Add(CurrentControllerIndexName, controller);

        return controller;
    }

public static IController GetCurrentController()
{
    if(HttpContext.Current.Items.Contains(CurrentControllerIndexName))
    {
        return (IController) HttpContext.Current.Items[CurrentControllerIndexName];
    }

    throw  new Exception("No Controller found in the Current HttpContext");
 }

我已经扩展了“DefaultControllerFactory”,并且正在使用 HttpContext 将当前使用的控制器存储在当前的 HttpRequest 中,现在可以正常工作。

CustomMessage 现在看起来像:

public class CustomMessage : IAddMessage
{
   public CustomMessage()
   {
   }

   public void Add(string text, MessageTypes messageTypes)
   {
       Controller controller = (Controller)CustomControllerFactory.GetCurrentController();
       //TODO
   } 
}

和我的城堡登记册

...
container.Register(Classes.FromAssemblyContaining<HomeController>().BasedOn<IController>().LifestylePerWebRequest());
container.Register(Component.For<IAddMessage>().ImplementedBy<CustomMessage>());
...

现在效果很好。

于 2013-08-31T09:43:23.900 回答