Skip to content

Instantly share code, notes, and snippets.

@jfromaniello
Created November 24, 2010 13:50
Show Gist options
  • Save jfromaniello/713672 to your computer and use it in GitHub Desktop.
Save jfromaniello/713672 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.CodeModel;
using PostSharp.Extensibility;
namespace VanAOP.PostSharp._4to
{
[Serializable]
[IntroduceInterface(typeof (IEditableObject), OverrideAction = InterfaceOverrideAction.Ignore)]
[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
public sealed class EditableAttribute : InstanceLevelAspect, IEditableObject
{
private IDictionary<string, LocationInterceptionArgs> tempValues;
private bool isInEditMode;
[IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
public void BeginEdit()
{
isInEditMode = true;
tempValues = new Dictionary<string, LocationInterceptionArgs>();
}
[IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
public void EndEdit()
{
isInEditMode = false;
AplicarCambios();
}
[IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
public void CancelEdit()
{
isInEditMode = false;
}
private void AplicarCambios()
{
foreach (var kv in tempValues)
{
kv.Value.ProceedSetValue();
}
}
[OnLocationSetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Field)]
public void OnFieldSet(LocationInterceptionArgs args)
{
if(!isInEditMode)
{
args.ProceedSetValue();
return;
}
tempValues[args.Location.Name] = args;
}
[OnLocationGetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Field)]
public void OnFieldGet(LocationInterceptionArgs args)
{
LocationInterceptionArgs result;
if (!isInEditMode || !tempValues.TryGetValue(args.Location.Name, out result))
{
args.ProceedGetValue();
return;
}
args.Value = result.Value;
}
}
[Editable]
public class CajaAhorro
{
public virtual string Codigo { get; set; }
public virtual string Titular { get; set; }
public virtual double Saldo { get; private set; }
public virtual void Acreditar(double importe)
{
Saldo += importe;
}
public virtual void Debitar(double importe)
{
Saldo -= importe;
}
}
[TestFixture]
public class Test
{
//private T CrearProxy<T>(params object[] arguments)
//{
// var proxyGenerator = new ProxyGenerator();
// return (T)proxyGenerator.CreateClassProxy(typeof(T),
// new[] { typeof(IEditableObject) },
// new IInterceptor[] { new EditableInterceptor() });
//}
[Test]
public void puedo_editar_y_confirmar()
{
var caja = new CajaAhorro();
caja.Titular = "Pedro";
((IEditableObject)caja).BeginEdit();
caja.Titular = "José";
caja.Titular.Should().Be.EqualTo("José");
((IEditableObject)caja).EndEdit();
caja.Titular.Should().Be.EqualTo("José");
}
[Test]
public void puedo_editar_y_cancelar()
{
var caja = new CajaAhorro();
caja.Titular = "Pedro";
((IEditableObject)caja).BeginEdit();
caja.Titular = "José";
((IEditableObject)caja).CancelEdit();
caja.Titular.Should().Be.EqualTo("Pedro");
}
[Test]
public void multiples_aspectos()
{
//var proxyGenerator = new ProxyGenerator();
//var cuenta = (CajaAhorro)proxyGenerator.CreateClassProxy(typeof(CajaAhorro),
// new[] { typeof(IEditableObject) },
// new IInterceptor[] { // ¿ ? // });
//cuenta.Titular = "Pedro";
//((IEditableObject)cuenta).BeginEdit();
//cuenta.Titular = "José";
//((IEditableObject)cuenta).CancelEdit();
}
[Test]
public void puedo_debitar_y_cancelar()
{
var caja = new CajaAhorro();
caja.Titular = "Pedro";
((IEditableObject)caja).BeginEdit();
caja.Acreditar(221);
((IEditableObject)caja).CancelEdit();
caja.Saldo.Should().Be.EqualTo(0);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment