这是我为解决我的问题所做的。它有点大,所以可能性能不高,但对我有用。
编辑
有关性能详细信息,请参阅此问题:C# using properties with value types with Delegate.CreateDelegate
发布属性更改内容的基类:
public abstract class PropertyChangePublisherBase : INotifyPropertyChanged
{
private Dictionary<string, PropertyInfo> _properties;
private bool _cacheProperties;
public bool CacheProperties
{
get { return _cacheProperties; }
set
{
_cacheProperties = value;
if (_cacheProperties && _properties == null)
_properties = new Dictionary<string, PropertyInfo>();
}
}
protected PropertyChangePublisherBase(bool cacheProperties)
{
CacheProperties = cacheProperties;
}
public bool ContainsBinding(PropertyChangedEventHandler handler)
{
if (PropertyChanged == null)
return false;
return PropertyChanged.GetInvocationList().Contains(handler);
}
public object GetPropertValue(string propertyName)
{
if (String.IsNullOrEmpty(propertyName) || String.IsNullOrWhiteSpace(propertyName))
throw new ArgumentException("Argument must be the name of a property of the current instance.", "propertyName");
return ProcessGetPropertyValue(propertyName);
}
protected virtual object ProcessGetPropertyValue(string propertyName)
{
if (_cacheProperties)
{
if (_properties.ContainsKey(propertyName))
{
return _properties[propertyName].GetValue(this, null);
}
else
{
var property = GetType().GetProperty(propertyName);
_properties.Add(propertyName, property);
return property.GetValue(this, null);
}
}
else
{
var property = GetType().GetProperty(propertyName);
return property.GetValue(this, null);
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
接收属性更改内容的基类:
public abstract class PropertyChangeSubscriberBase
{
protected readonly string _propertyName;
protected virtual object Value { get; set; }
protected PropertyChangeSubscriberBase(string propertyName, PropertyChangePublisherBase bindingPublisher)
{
_propertyName = propertyName;
AddBinding(propertyName, this, bindingPublisher);
}
~PropertyChangeSubscriberBase()
{
RemoveBinding(_propertyName);
}
public void Unbind()
{
RemoveBinding(_propertyName);
}
#region Static Fields
private static List<string> _bindingNames = new List<string>();
private static List<PropertyChangeSubscriberBase> _subscribers = new List<PropertyChangeSubscriberBase>();
private static List<PropertyChangePublisherBase> _publishers = new List<PropertyChangePublisherBase>();
#endregion
#region Static Methods
private static void PropertyChanged(object sender, PropertyChangedEventArgs args)
{
string propertyName = args.PropertyName;
if (_bindingNames.Contains(propertyName))
{
int i = _bindingNames.IndexOf(propertyName);
var publisher = _publishers[i];
var subscriber = _subscribers[i];
subscriber.Value = publisher.GetPropertValue(propertyName);
}
}
public static void AddBinding(string propertyName, PropertyChangeSubscriberBase subscriber, PropertyChangePublisherBase publisher)
{
if (!_bindingNames.Contains(propertyName))
{
_bindingNames.Add(propertyName);
_publishers.Add(publisher);
_subscribers.Add(subscriber);
if (!publisher.ContainsBinding(PropertyChanged))
publisher.PropertyChanged += PropertyChanged;
}
}
public static void RemoveBinding(string propertyName)
{
if (_bindingNames.Contains(propertyName))
{
int i = _bindingNames.IndexOf(propertyName);
var publisher = _publishers[i];
_bindingNames.RemoveAt(i);
_publishers.RemoveAt(i);
_subscribers.RemoveAt(i);
if (!_publishers.Contains(publisher))
publisher.PropertyChanged -= PropertyChanged;
}
}
#endregion
}
用于订阅属性更改内容的实际类:
public sealed class PropertyChangeSubscriber<T> : PropertyChangeSubscriberBase
{
private PropertyChangePublisherBase _publisher;
public new T Value
{
get
{
if (base.Value == null)
return default(T);
if (base.Value.GetType() != typeof(T))
throw new InvalidOperationException(String.Format("Property {0} on object of type {1} does not match the type Generic type specified {2}.", _propertyName, _publisher.GetType(), typeof(T)));
return (T)base.Value;
}
set { base.Value = value; }
}
public PropertyChangeSubscriber(string propertyName, PropertyChangePublisherBase bindingPublisher)
: base(propertyName, bindingPublisher)
{
_publisher = bindingPublisher;
}
}
这是一个类的示例,其中包含您希望收到通知的属性:
public class ExamplePublisher: PropertyChangedPublisherBase
{
private string _id;
private bool _testBool;
public string Id
{
get { return _id; }
set
{
if (value == _id) return;
_id = value;
RaisePropertyChanged("Id");
}
}
public bool TestBool
{
get { return _testBool; }
set
{
if (value.Equals(_testBool)) return;
_testBool = value;
RaisePropertyChanged("TestBool");
}
}
}
下面是一个类的示例,当上面的类中的属性发生变化时会得到通知:
public class ExampleReceiver
{
public PropertyChangeSubscriber<string> Id { get; set; }
public PropertyChangeSubscriber<bool> TestBool { get; set; }
public MyExampleClass(PropertyChangePublisherBase publisher)
{
Id = new PropertyChangeSubscriber<string>("Id", publisher);
TestBool = new PropertyChangeSubscriber<bool>("TestBool", publisher);
}
}