Ранее я писал про механизмы AOP в Unity 1.0 (или 1.2 на тот момент). Недавно увидел этот пост, с примером для Unity 2.0.
В первой версии было фактически две возможности для задания перехватчиков вызовов: это атрибуты на классах или сложный код (или xml), задающий условия по которым будут срабатывать обработчики вызовов.
Оба варианта довольно плохие, первый заставляет править существующий код, второй просто неподъемный. В Unity 2.0 исправили ситуацию с помощью так называемых InterceptionBehavior.
Пример кода из поста в новом стиле.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System.Transactions;
namespace Unity20Interception
{
public interface IAccountService
{
// Хотим чтобы метод Withdraw выполнялся под транзакцией,
// Но ничего помечать не будем.
void Withdraw(decimal amount);
}
public class AccountService : IAccountService
{
public void Withdraw(decimal amount)
{
if (amount < 0 || amount > 1000)
throw new ArgumentOutOfRangeException("amount");
}
}
//Собственно класс обработчика вызовов
public class TransactionBehavior: IInterceptionBehavior
{
#region IInterceptionBehavior Members
public IEnumerable<Type> GetRequiredInterfaces()
{
return Enumerable.Empty<Type>();
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
using (TransactionScope transaction = new TransactionScope())
{
var result = getNext()(input, getNext);
if (result.Exception == null)
{
// исключений не возникло, завершим транзакцию
transaction.Complete();
Console.WriteLine("Transaction commited");
}
return result;
}
}
public bool WillExecute
{
get { return true; }
}
#endregion
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().AddNewExtension<Interception>();
container
.RegisterType<IAccountService, AccountService>(
//Устанавливаем способ перехвата
new Interceptor<InterfaceInterceptor>(),
//Устанавливаем обработчик
new InterceptionBehavior<TransactionBehavior>()
);
var service = container.Resolve<IAccountService>();
service.Withdraw(33); // транзакция пройдет успешно
service.Withdraw(-6);
}
}
Также новых механизм перехвата позволяет добавлять к сгенерированному классу-перехватчику необходимые интерфейсы. Например можно сделать таким образом behavior, который добавляет реализацию INotifyPropertyChanged.
http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx
