class ObservableDataPropertyAttribute : Attribute
{
}
class DependsOnAttribute : Attribute
{
public string Dependency { get; private set; }
public DependsOnAttribute(string dependency)
{
Dependency = dependency;
}
}
class ValidationAttribute : Attribute
{
}
abstract class ObservableType : IDisposable
{
//When Dispose is called, all Observables are terminated (and send the OnCompleted signal to the Observers)
public abstract void Dispose();
//The OnNext event is only triggered *once* when multiple properties are changed.
//If two properties of different types should be listened to, then their base common type should be used (e.g. System.Object)
public IObservable<T> GetObservableForProperties<T>(params string[] propertyNames)
{
//TODO
return null;
}
protected static T New<T>() where T : ObservableType
{
//TODO: Implement this.
return null;
}
}
abstract class Person : ObservableType
{
[ObservableDataProperty]
public abstract string FullName { get; set; }
[DependsOn("FullName")]
public char FirstNameLetter {
get { return FullName[0]; }
}
[ObservableDataProperty]
public virtual int Age
{
get;
[Validation]
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("age");
}
}
public static Person New(string fullName)
{
var person = ObservableType.New<Person>();
person.FullName = fullName;
return person;
}
}
class Program
{
static void Main(string[] args)
{
var person = Person.New("Default Name");
using (var personNameListener = person.GetObservableForProperties<string>("FullName").Subscribe(newName =>
{
//It is also possible to listen to FirstNameLetter. The events are sent at the same time, since FirstNameLetter depends on FullName.
Console.WriteLine("New Name {0}", newName);
}))
{
person.FullName = "Some New Value";
}
}
}