温莎城堡建设

发布于 2024-10-01 08:46:27 字数 302 浏览 0 评论 0原文

Castle Windsor 是否具有与 Unity 的 BuildUp() 等效的功能,您可以使用属性来装饰类属性,并使容器将值传递给现有对象实例?

例如在Unity中:

Statistics existingInstance = new Statistics();  
container.BuildUp(existingInstance)

class Statistics  
{  
  [Dependency]  
  public ICalculator Calculator { get; set; }  

Does Castle Windsor have an equivalent to Unity's BuildUp() whereby you can decorate class properties with attributes and have the container pass in values to an existing object instance?

e.g. in Unity:

Statistics existingInstance = new Statistics();  
container.BuildUp(existingInstance)

class Statistics  
{  
  [Dependency]  
  public ICalculator Calculator { get; set; }  

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

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

发布评论

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

评论(2

一口甜 2024-10-08 08:46:27

不过,您可以自己编写此功能的代码。例如,下面是一个 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-08 08:46:27

看起来答案是 Castle Windsor 无法通过属性或注入方法将依赖项注入到现有对象实例中:

重复问题

looks like the answer is that Castle Windsor can't inject dependencies into an existing object instance either by attributes or an injection method:

Duplication Question

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