在MEF中,可以使用以下内容设置现有对象的依赖关系:
container.SatisfyImportsOnce(instance);
是否可以对Castle Windsor执行相同操作?
我正在使用(阅读:学习)Caliburn.Micro,并尝试将模板项目从MEF更新到Windsor,这是我遇到问题的地方。
答案 0 :(得分:2)
抱歉Neil,Windsor没有这个功能
如果存在该服务的注册组件,Windsor将解析属性依赖项(它认为是可选的依赖项),例如ILogger属性。但这仅在组件激活期间发生...当组件第一次构造时,无法将Windsor传递给现有实例并将组件注入属性。
答案 1 :(得分:1)
使用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
}
}
答案 2 :(得分:1)
但您可以自己编写此功能。例如,这是一个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,我们现在可以使用Castle Windsors DI功能将任何类型注入我们的MVC应用程序中的任何Action Filter。为了完整地完成这个答案,下面是一个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();
}
}