Castle Windsor: установить зависимости компонентов от существующего объекта - PullRequest
2 голосов
/ 26 ноября 2010

В MEF можно установить зависимости для существующего объекта, используя что-то вроде:

container.SatisfyImportsOnce(instance);

Можно ли сделать то же самое с Castle Windsor ?

Я использую (читай: обучение) Caliburn.Micro и пытаюсь обновить проект шаблона с MEF до Windsor, вот где я столкнулся с проблемой.

Ответы [ 3 ]

2 голосов
/ 30 ноября 2010

Извините, Нил, Виндзор не имеет этой функции

FAQ по Виндзорскому замку

Windsor разрешит зависимость свойства (которую он считает необязательной зависимостью), такую ​​как свойство ILogger, если для этой службы есть зарегистрированный компонент. Но это происходит только во время активации компонента ... когда компонент создается в первый раз, невозможно передать Windsor существующий экземпляр и внедрить компоненты в свойства.

1 голос
/ 01 мая 2013

Однако вы можете закодировать эту функцию самостоятельно. Например, вот 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 мы ищем неинициализированные (нулевые) свойства, а затем проверяем, был ли тип зарегистрирован в Castle Windsor. Если это так, мы устанавливаем свойство.

Заменив фильтр FilterAttributeFilterProvider по умолчанию на наш собственный (выше) в файле global.asax, теперь мы можем использовать функции DI Castle Windsors для добавления любого типа в любой фильтр действий в нашем приложении MVC. Чтобы завершить этот ответ полностью, вот пример класса приложения global.asax с установкой Castle Windsor для внедрения зависимости (Controller (во время создания экземпляра)) и ActionFilter (во время использования):

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();
  }
}
1 голос
/ 26 ноября 2010

С помощью 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
  }
}
...