|
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
namespace Pfz.DistributableObservablePoco.Common
{
public sealed class DynamicDop:
DynamicObject,
IDynamicDop
{
private sealed class _Data
{
internal readonly PropertyChangedEventArgs _args;
internal object _value;
internal _Data(PropertyChangedEventArgs args)
{
_args = args;
}
}
private readonly ConcurrentDictionary<string, _Data> _properties = new ConcurrentDictionary<string, _Data>();
private readonly Func<string, _Data> _createData = (propertyName) => new _Data(new PropertyChangedEventArgs(propertyName));
public object GetValue(string propertyName)
{
if (propertyName == null)
throw new ArgumentNullException("propertyName");
_Data data;
_properties.TryGetValue(propertyName, out data);
if (data == null)
return null;
return data._value;
}
public void SetValue(string propertyName, object value)
{
if (propertyName == null)
throw new ArgumentNullException("propertyName");
var handler = PropertyChanged;
var dopHandler = DopPropertyChanged;
_Data data;
if (handler == null && dopHandler == null)
{
if (value != null)
{
data = _properties.GetOrAdd(propertyName, _createData);
data._value = value;
}
else
{
_Data oldData;
_properties.TryRemove(propertyName, out oldData);
}
return;
}
if (value == null)
{
if (!_properties.TryRemove(propertyName, out data))
return;
}
else
{
data = _properties.GetOrAdd(propertyName, _createData);
object oldValue = data._value;
if (oldValue != null)
{
Type type = value.GetType();
if (type == oldValue.GetType())
{
if (type.IsValueType)
{
if (object.Equals(value, oldValue))
return;
}
else
{
if (value == oldValue)
return;
}
}
}
data._value = value;
}
if (handler != null)
handler(this, data._args);
if (dopHandler != null)
dopHandler(this, propertyName, value);
}
public IEnumerable<KeyValuePair<string, object>> EnumeratePropertiesAndValues()
{
foreach(var pair in _properties)
{
string propertyName = pair.Key;
object value = pair.Value._value;
yield return new KeyValuePair<string, object>(propertyName, value);
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = GetValue(binder.Name);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
SetValue(binder.Name, value);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
public event DopPropertyChangedEventHandler DopPropertyChanged;
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I started to program computers when I was 11 years old, as a hobbyist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.
At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do their work easier, faster and with less errors.
Want more info or simply want to contact me?
Take a look at:
http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com
Codeproject MVP 2012, 2015 & 2016
Microsoft MVP 2013-2014 (in October 2014 I started working at Microsoft, so I can't be a Microsoft MVP anymore).