Autofac - 委托工厂 + 类型拦截器在一起
Autofac - Delegate Factories + Type Interceptors together
我正在尝试让 AutoFac Delegate Factories & Type Interceptors 相互配合,但我似乎无法获得我想要的行为。
(http://docs.autofac.org/en/latest/advanced/delegate-factories.html)
(http://docs.autofac.org/en/latest/advanced/interceptors.html)
在下面的示例中,我希望调用 IQuoteService.GetQuote(...) 被 CallLogger 拦截器拦截。
我已经尝试了两个 Enable___();启用拦截的扩展方法,但其中 none 似乎正确拦截了调用。
我怀疑问题出在 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();
}
}
}
// 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>();
在我看来,您缺少 IPortfolio
的 DynamicProxy
和 IInterceptor
类型之间的关联。
这可以通过注册来解决:
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);
}
我正在尝试让 AutoFac Delegate Factories & Type Interceptors 相互配合,但我似乎无法获得我想要的行为。
(http://docs.autofac.org/en/latest/advanced/delegate-factories.html) (http://docs.autofac.org/en/latest/advanced/interceptors.html)
在下面的示例中,我希望调用 IQuoteService.GetQuote(...) 被 CallLogger 拦截器拦截。
我已经尝试了两个 Enable___();启用拦截的扩展方法,但其中 none 似乎正确拦截了调用。
我怀疑问题出在 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();
}
}
}
// 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>();
在我看来,您缺少 IPortfolio
的 DynamicProxy
和 IInterceptor
类型之间的关联。
这可以通过注册来解决:
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);
}