温莎没有解决截获的组件

时间:2013-03-20 20:50:18

标签: c# castle-windsor interceptor

任何人都可以解释为什么这不起作用?如果从IFoo的注册中删除拦截器并解析一个Bar,则会得到一个Foo(MyFoo不为null)。但是使用拦截器,Foo不再解决了。

为什么呢?我怎么知道为什么它不能通过记录或跟踪来解决?

版本:

  • Castle.Core:3.2
  • Castle.Windsor:3.2
  • .NET 4.5
  • C#5

    using Castle.DynamicProxy;
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using System;
    
    namespace Sandbox
    {
    public interface IFooInterceptor : IInterceptor { }
    
    public interface IFoo
    {
        void Print();
    }
    
    public interface IBar
    {
        IFoo MyFoo { get; set; }
    }
    
    public class Foo : IFoo
    {
        public void Print()
        {
            Console.WriteLine("Print");
        }
    }
    
    public class FooInterceptor : IFooInterceptor, IInterceptor
    {
    
        public void Intercept(IInvocation invocation)
        {
            Console.WriteLine("Awesome");
            invocation.Proceed();
        }
    }
    
    public class Bar : IBar
    {
        public virtual IFoo MyFoo { get; set; }
    }
    
    class Program
    {
    
        static void Main(string[] args)
        {
            IWindsorContainer container = new WindsorContainer()
                .Register(
                    Component.For<IBar>().ImplementedBy<Bar>().LifestyleTransient(),
                    Component.For<IFoo>().ImplementedBy<Foo>().LifestyleTransient().Interceptors<IFooInterceptor>(),
                    Component.For<IFooInterceptor>().ImplementedBy<FooInterceptor>().LifestyleTransient()
                );
    
            var bar = container.Resolve<IBar>();
            var foo = container.Resolve<IFoo>();  // this isn't null
            bar.MyFoo.Print();                    // exception: bar.MyFoo is null
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    
    }
    }
    

编辑:我刚刚发现(主要是偶然)将拦截器配置从接口更改为具体类。但是,我正在注册拦截器及其接口,因此原始问题稍作修改:为什么接口规范失败(默默地,不少)?

1 个答案:

答案 0 :(得分:2)

Castle将属性作为可选依赖项处理,但默认情况下应注入它们。但似乎与拦截器结合使用时,这些可选的依赖关系无法正确解析。

您可以做的是通过更改Bar以使用构造函数注入来使您的依赖项成为必需:

public class Bar : IBar
{
    public Bar(IFoo foo)
    {
        MyFoo = foo;
    }

    public virtual IFoo MyFoo { get; private set; }
}

或者使用明确标记为Properties的条目注册条:

Component.For<IBar>().ImplementedBy<Bar>().LifestyleTransient()
    .Properties(Prop‌​ertyFilter.RequireAll)

注意:在制作中,您应该使用PropertiesRequired方法而不是Properties方法,因为它现在已经过时了。

我也发现这个github问题似乎也很重要:Bug - optional dependencies not provided