I am trying to get AutoFac Delegate Factories & Type Interceptors to play nicely with each other, but I cannot seem to get the behaviour I want.
(http://docs.autofac.org/en/latest/advanced/delegate-factories.html) (http://docs.autofac.org/en/latest/advanced/interceptors.html)
In the example below, I want calls to the IQuoteService.GetQuote(...) to be intercepted by the CallLogger interceptor.
I've tried both of the Enable___(); extension methods for enabling interception, but none of them seem to correctly intercept the call.
I suspect the problem is the way that Autofac is registering the proxy and the signature of the delegate, but to be honest I am a little stuck... I don't know Autofac as well as I know Castle Windsor, but this project is using Autofac.
ANSWERED BELOW
Code updated to working example:
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();
}
}
}