【问题标题】:Autofac - Delegate Factories + Type Interceptors togetherAutofac - 一起委托工厂 + 类型拦截器
【发布时间】:2017-05-14 07:42:27
【问题描述】:

我正在尝试让 AutoFac Delegate FactoriesType Interceptors 相互配合,但我似乎无法获得我想要的行为。

(http://docs.autofac.org/en/latest/advanced/delegate-factories.html) (http://docs.autofac.org/en/latest/advanced/interceptors.html)

在下面的示例中,我希望 CallLogger 拦截器拦截对 IQuoteService.GetQuote(...) 的调用。

我已经尝试了两个 Enable___();用于启用拦截的扩展方法,但它们似乎都没有正确拦截调用。

我怀疑问题出在 Autofac 注册代理和代表签名的方式上,但老实说我有点卡住了......我不了解 Autofac 以及了解 Castle Windsor,但是这个项目正在使用 Autofac。

答案如下

代码更新为工作示例:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autofac;
using Autofac.Extras.DynamicProxy2;
using Castle.DynamicProxy;

namespace AutofacTest
{
    public class Shareholding
    {
        public delegate Shareholding Factory(string symbol, uint holding);

        private readonly IQuoteService _quoteService;

        public Shareholding(string symbol, uint holding, IQuoteService quoteService)
        {
            _quoteService = quoteService;
            Symbol = symbol;
            Holding = holding;
        }

        public string Symbol { get; private set; }

        public uint Holding { get; set; }

        public decimal Value
        {
            get { return _quoteService.GetQuote(Symbol) * Holding; }
        }
    }

    public class Portfolio
    {
        private readonly IList<Shareholding> _holdings = new List<Shareholding>();
        private readonly Shareholding.Factory _shareholdingFactory;

        public Portfolio(Shareholding.Factory shareholdingFactory)
        {
            _shareholdingFactory = shareholdingFactory;
        }

        public decimal Value
        {
            get { return _holdings.Sum(h => h.Value); }
        }

        public void Add(string symbol, uint holding)
        {
            _holdings.Add(_shareholdingFactory(symbol, holding));
        }
    }

    public interface IQuoteService
    {
        decimal GetQuote(string symbol);
    }

    public class QuoteService : IQuoteService
    {
        public decimal GetQuote(string symbol)
        {
            return 10m;
        }
    }

    public class CallLogger : IInterceptor
    {
        private readonly TextWriter _output;

        public CallLogger(TextWriter output)
        {
            _output = output;
        }

        public void Intercept(IInvocation invocation)
        {
            _output.Write("Calling method {0} with parameters {1}... ",
                invocation.Method.Name,
                string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));

            invocation.Proceed();

            _output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<Shareholding>();
            builder.RegisterType<Portfolio>();
            builder.Register(c => new CallLogger(Console.Out));

            builder.RegisterType<QuoteService>()
                   .As<IQuoteService>()
                   .EnableInterfaceInterceptors()
                   .InterceptedBy(typeof(CallLogger));

            var container = builder.Build();

            var portfolio = container.Resolve<Portfolio>();
            portfolio.Add("ABC", 1234);
            portfolio.Add("DEF", 4567);

            Console.WriteLine(portfolio.Value);
            Console.ReadKey();
        }
    }
}

【问题讨论】:

    标签: c# aop autofac interceptor autofac-module


    【解决方案1】:
    // Magic?
    
    builder.RegisterType<Portfolio>()
           .As<IPortfolio>()
           .EnableInterfaceInterceptors()
           .InterceptedBy(typeof(CallLogger));;
    builder.Register(c => new CallLogger(Console.Out));
    var container = builder.Build();
    var isResolved = container.Resolve<IPortfolio>();
    

    【讨论】:

    • 不工作恐怕,我已经用你的代码建议更新了我的问题......我相信问题是 Portfolio 依赖于 Shareholding.Factory 委托和 IQuoteService在 Shareholding 的构造函数上解决。
    【解决方案2】:

    在我看来,您缺少IPortfolioDynamicProxyIInterceptor 类型之间的关联。

    这可以通过注册来解决:

    builder.RegisterType<Portfolio>()
        .As<IPortfolio>()
        .EnableInterfaceInterceptors()
        .InterceptedBy(typeof(CallLogger));
    

    或通过InterceptAttribute

    [Intercept(typeof(CallLogger))]
    public interface IPortfolio
    {
        decimal Value { get; }
        void Add(string symbol, uint holding);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-20
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多