温莎城堡:设置现有对象的组件依赖关系

发布于 2024-10-04 21:08:56 字数 390 浏览 1 评论 0原文

MEF 中,可以使用以下内容设置现有对象的依赖关系:

container.SatisfyImportsOnce(instance);

是否可以执行相同的操作温莎城堡

我正在使用(阅读:学习)Caliburn.Micro,并尝试将模板项目从 MEF 更新到 Windsor ,这就是我遇到这个问题的地方。

In MEF it's possible to set the dependencies for an existing object using something like:

container.SatisfyImportsOnce(instance);

Is it possible to do the same with Castle Windsor?

I'm using (read: learning) Caliburn.Micro, and trying to update the template project from MEF to Windsor, which is where I've come across the issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

分開簡單 2024-10-11 21:09:06

不过,您可以自己编写此功能的代码。例如,下面是一个 ASP.NET MVC FilterAttributeFilterProvider,用于将属性注入到属性操作过滤器中。

  public class AttributeFilterProvider : FilterAttributeFilterProvider
  {
    public AttributeFilterProvider(IKernel kernel)
    {
      _kernel = kernel;
    }

    private readonly IKernel _kernel;

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
      var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
      BuildUpAttributeDependancies(attributes);
      return attributes;
    }

    protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
      var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
      BuildUpAttributeDependancies(attributes);
      return attributes;
    }

    private void BuildUpAttributeDependancies(IEnumerable<FilterAttribute> attributes)
    {
      foreach (var attribute in attributes)
      {
        var propInfos = attribute.GetType().GetProperties().Where(x => x.GetValue(attribute) == null).AsEnumerable();
        foreach (var pi in propInfos)
        {
          if (_kernel.HasComponent(pi.PropertyType))
          {
            var service = _kernel.Resolve(pi.PropertyType);
            pi.SetValue(attribute, service);
          }
        }
      }
    }
  }

在 BuildUpAttributeDependancies 方法中,我们查找未初始化 (null) 的属性,然后检查该类型是否已在 Castle Windsor 中注册。如果有,我们设置该属性。

通过将 global.asax 文件中的默认 FilterAttributeFilterProvider 替换为我们自定义的 FilterAttributeFilterProvider(如上),我们现在可以使用 Castle Windsors DI 功能将任何类型注入到 MVC 应用程序中的任何 Action Filter 中。为了完整地完成这个答案,下面是一个 global.asax 应用程序类的示例,其中包含用于控制器(在实例化时)和 ActionFilter(在使用时)依赖注入的 Castle Windsor 设置:

public class MvcApplication : System.Web.HttpApplication
{
  private static IWindsorContainer _container;

  private static void BootstrapContainer()
  {
    _container = new WindsorContainer()
        .Install(FromAssembly.This());

    var controllerFactory = new ControllerFactory(_container.Kernel);
    ControllerBuilder.Current.SetControllerFactory(controllerFactory);
  }

  private static void BootstrapFilters()
  {
    var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
    FilterProviders.Providers.Remove(oldProvider);

    var provider = new AttributeFilterProvider(_container.Kernel);
    FilterProviders.Providers.Add(provider);
  }

  protected void Application_Start()
  {
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    BootstrapContainer();
    BootstrapFilters();
  }
}

You can however code this functionality yourself. For example, here is an ASP.NET MVC FilterAttributeFilterProvider, used to inject proprties onto attribute action filters.

  public class AttributeFilterProvider : FilterAttributeFilterProvider
  {
    public AttributeFilterProvider(IKernel kernel)
    {
      _kernel = kernel;
    }

    private readonly IKernel _kernel;

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
      var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
      BuildUpAttributeDependancies(attributes);
      return attributes;
    }

    protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
      var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
      BuildUpAttributeDependancies(attributes);
      return attributes;
    }

    private void BuildUpAttributeDependancies(IEnumerable<FilterAttribute> attributes)
    {
      foreach (var attribute in attributes)
      {
        var propInfos = attribute.GetType().GetProperties().Where(x => x.GetValue(attribute) == null).AsEnumerable();
        foreach (var pi in propInfos)
        {
          if (_kernel.HasComponent(pi.PropertyType))
          {
            var service = _kernel.Resolve(pi.PropertyType);
            pi.SetValue(attribute, service);
          }
        }
      }
    }
  }

In the BuildUpAttributeDependancies method, we look for un-initialised (null) properties, and then check to see if the type has been registered with Castle Windsor. If it has, we set the property.

By replacing the default FilterAttributeFilterProvider with our custom one (above) in the global.asax file we can now use Castle Windsors DI features to inject any type onto any Action Filter in our MVC application. To complete this answer fully, here is an example of a global.asax application class with Castle Windsor setup for both Controller (at instantiation time) and ActionFilter (at usage time) dependancy injection:

public class MvcApplication : System.Web.HttpApplication
{
  private static IWindsorContainer _container;

  private static void BootstrapContainer()
  {
    _container = new WindsorContainer()
        .Install(FromAssembly.This());

    var controllerFactory = new ControllerFactory(_container.Kernel);
    ControllerBuilder.Current.SetControllerFactory(controllerFactory);
  }

  private static void BootstrapFilters()
  {
    var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
    FilterProviders.Providers.Remove(oldProvider);

    var provider = new AttributeFilterProvider(_container.Kernel);
    FilterProviders.Providers.Add(provider);
  }

  protected void Application_Start()
  {
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    BootstrapContainer();
    BootstrapFilters();
  }
}
伴随着你 2024-10-11 21:09:04

使用 Castle Windsor,您可以向容器注册现有实例,这是您正在寻找的东西吗?

var instance = new Logger();
var container = new WindsorContainer();

container.Register(Component.For<ILogger>().Instance(instance))

在哪里

public interface ILogger
{
  void LogException(Exception ex);
}

public class Logger : ILogger
{
  public void LogException(Exception ex)
  {
    // Log exception
  }
}

With Castle Windsor you can register an existing instance with the container, is this the kind of thing you are looking for?

var instance = new Logger();
var container = new WindsorContainer();

container.Register(Component.For<ILogger>().Instance(instance))

where

public interface ILogger
{
  void LogException(Exception ex);
}

public class Logger : ILogger
{
  public void LogException(Exception ex)
  {
    // Log exception
  }
}
菩提树下叶撕阳。 2024-10-11 21:09:02

抱歉尼尔,温莎没有该功能

城堡Windsor 常见问题

如果存在该服务的注册组件,Windsor 将解析属性依赖项(它认为是可选依赖项),例如 ILogger 属性。但这仅发生在组件激活期间......当第一次构造组件时,无法向 Windsor 传递现有实例并将组件注入属性中。

Sorry Neil, Windsor doesn't have that feature

Castle Windsor FAQ

Windsor will resolve a property dependency (which it considers an optional dependency) such as an ILogger property if there is a registered component for that service. But this only happens during component activation...when the component is constructed the first time, there is no way to pass Windsor an existing instance and inject components into properties.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文