Skip to content

Instantly share code, notes, and snippets.

@jtheisen
Last active May 31, 2017 19:27
Show Gist options
  • Save jtheisen/f6de30d6dfbd8355194b9469eb18e3be to your computer and use it in GitHub Desktop.
Save jtheisen/f6de30d6dfbd8355194b9469eb18e3be to your computer and use it in GitHub Desktop.
using System;
using System.ComponentModel;
namespace AssemblyToProcess
{
#region The interfaces we need to define our implementations with.
// See sample below for an explanation of the type parameters.
public interface IPropertyImplementation<ValueInterface, ContainerInterface, Value, Container, MixIn>
where Value : ValueInterface
where Container : ContainerInterface
where MixIn : struct
{
Value Get(Container self, ref MixIn mixIn);
void Set(Container self, ref MixIn mixIn, Value value);
}
public interface IPreviousPropertyImplementation<Value>
{
String GetPropertyName();
Value Get();
void Set(Value value);
}
#endregion
#region The sample implementation: Implementing INotifyPropertyChanged!
/// <summary>
/// Our property implementations need a common mix in that implements the event.
/// </summary>
/// <typeparam name="Container"></typeparam>
public struct MyMixIn<Container> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void Fire(Container self, String propertyName)
{
PropertyChanged?.Invoke(self, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// We have an example property implementation that will fire a PropertyChanged event on setting.
/// </summary>
/// <typeparam name="Value">The type of the property (Decimal or Int32 in our sample).</typeparam>
/// <typeparam name="Container">The type of the object we have the properties on.</typeparam>
/// <typeparam name="OriginalImplementation">Made by the weaver to allow for access to the previous properties.</typeparam>
public struct MyPropertyImplementation<Value, Container, OriginalImplementation>
: IPropertyImplementation<IComparable<Value>, Object, Value, Container, MyMixIn<Container>>
where Value : IComparable<Value>
where OriginalImplementation : IPreviousPropertyImplementation<Value>
{
public OriginalImplementation originalImplementation;
public Value Get(Container self, ref MyMixIn<Container> mixIn)
{
return originalImplementation.Get();
}
public void Set(Container self, ref MyMixIn<Container> mixIn, Value value)
{
originalImplementation.Set(value);
mixIn.Fire(self, originalImplementation.GetPropertyName());
}
}
/// <summary>
/// This is our sample class to be rewoven. It can actually really live in the
/// same assembly as the property implementation above.
/// </summary>
public class ClassToHaveItsPropertiesModified
{
public Decimal Decimal { get; set; }
public Int32 Int32 {
get {
return (Int32)Decimal;
}
set {
Decimal = Int32;
}
}
}
#endregion
#region The produced wool.
// These two accessors will be (properly) implemented by the weaver and delegate to
// the original setter and getter. (As well as giving access to the name. Well, we need it
// and it has to go somewhere.)
public struct TheImplementationWrappingDecimalAccessors : IPreviousPropertyImplementation<Decimal>
{
public String GetPropertyName() => throw new NotImplementedException();
public Decimal Get() => throw new NotImplementedException();
public void Set(Decimal value) => throw new NotImplementedException();
}
public struct TheImplementationWrappingInt32Accessors : IPreviousPropertyImplementation<Int32>
{
public String GetPropertyName() => throw new NotImplementedException();
public Int32 Get() => throw new NotImplementedException();
public void Set(Int32 value) => throw new NotImplementedException();
}
/// <summary>
/// The final class the weaver would produce. It's INotifyPropertyChanged since
/// the mix in is.
/// </summary>
public class ClassThatHadItsPropertiesModified
: INotifyPropertyChanged
{
#region Delegating INotifyPropertyChanged to the mix in.
MyMixIn<ClassThatHadItsPropertiesModified> myMixIn;
public event PropertyChangedEventHandler PropertyChanged {
add {
myMixIn.PropertyChanged += value;
}
remove {
myMixIn.PropertyChanged -= value;
}
}
#endregion
#region Decimal
TheImplementationWrappingDecimalAccessors decimalAccessors;
public MyPropertyImplementation<
Decimal,
ClassThatHadItsPropertiesModified,
TheImplementationWrappingDecimalAccessors
>
decimalImplementation;
public ClassThatHadItsPropertiesModified()
{
decimalImplementation.originalImplementation = decimalAccessors;
}
public Decimal Decimal {
get {
return decimalImplementation.Get(this, ref myMixIn);
}
set {
decimalImplementation.Set(this, ref myMixIn, value);
}
}
#endregion
#region Int32
TheImplementationWrappingDecimalAccessors int32Accessors;
public MyPropertyImplementation<
Int32,
ClassThatHadItsPropertiesModified,
TheImplementationWrappingInt32Accessors
>
int32Implementation;
public Int32 Int32 {
get {
return int32Implementation.Get(this, ref myMixIn);
}
set {
int32Implementation.Set(this, ref myMixIn, value);
}
}
#endregion
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment