Tôi không có nhiều thêm, nhưng tôi đã thấy rằng tôi cần phải gọi MyConstructor(): base() không có tham số trong 1 trường hợp. Tôi có một lớp cơ sở thực hiện INotifyPropertyChanged theo cách mà tôi có hàm đăng ký ảo (RegisterProperties() ảo. Khi tôi ghi đè lên nó, nó được gọi trong constructor cơ sở. Vì vậy, tôi cuối cùng phải gọi nó trong các lớp con có nguồn gốc gần đây nhất vì cơ sở đã được gọi rõ ràng trước khi ghi đè ảo được nhận ra. Thuộc tính của tôi không thông báo trừ khi tôi làm điều này. Toàn bộ lớp cơ sở là dưới đây.
Tôi đã thêm một lớp con DatabaseTraits ngay bên dưới nó. Nếu không có lệnh base() rỗng, thuộc tính của tôi không gọi OnPropertyChanged().
[DataContract]
public abstract class DataModelBase : INotifyPropertyChanged, IDataErrorInfo {
#region Properties
[IgnoreDataMember]
public object Self {
get { return this; }
//only here to trigger change
set { OnPropertyChanged("Self"); }
}
#endregion Properties
#region Members
[IgnoreDataMember]
public Dispatcher Dispatcher { get; set; }
[DataMember]
private Dictionary<object, string> _properties = new Dictionary<object, string>();
#endregion Members
#region Initialization
public DataModelBase() {
if(Application.Current != null) Dispatcher = Application.Current.Dispatcher;
_properties.Clear();
RegisterProperties();
}
#endregion Initialization
#region Abstract Methods
/// <summary>
/// This method must be defined
/// </summar
protected abstract void RegisterProperties();
#endregion Abstract Methods
#region Behavior
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool RegisterProperty<T>(ref T property, string propertyName) {
//causes problems in design mode
//if (property == null) throw new Exception("DataModelBase.RegisterProperty<T> : ref T property cannot be null.");
if (_properties.ContainsKey(property)) return false;
_properties.Add(property, propertyName);
return true;
}
protected string GetPropertyName<T>(ref T property) {
if (_properties.ContainsKey(property))
return _properties[property];
return string.Empty;
}
protected bool SetProperty<T>(ref T property, T value) {
//if (EqualityComparer<T>.Default.Equals(property, value)) return false;
property = value;
OnPropertyChanged(GetPropertyName(ref property));
OnPropertyChanged("Self");
return true;
}
[OnDeserialized]
public void AfterSerialization(StreamingContext context) {
if (Application.Current != null) Dispatcher = Application.Current.Dispatcher;
//---for some reason this member is not allocated after serialization
if (_properties == null) _properties = new Dictionary<object, string>();
_properties.Clear();
RegisterProperties();
}
#endregion Behavior
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotifyPropertyChanged Members
#region IDataErrorInfo Members
string IDataErrorInfo.Error {
get { throw new NotImplementedException(); }
}
string IDataErrorInfo.this[string propertyName] {
get { throw new NotImplementedException(); }
}
#endregion IDataErrorInfo Members
} //End class DataModelBaseclass DataModelBase
/*I decided to add an example subclass*/
[DataContract]
public abstract class DatabaseTraits : DataModelBase {
#region Properties
private long _id = -1;
[DataMember]
public long Id {
get { return _id; }
set { SetProperty(ref _id, value); }
}
private bool _isLocked = false;
[DataMember]
public bool IsLocked {
get { return _isLocked; }
set { SetProperty(ref _isLocked, value); }
}
private string _lockedBy = string.Empty;
[DataMember]
public string LockedBy {
get { return _lockedBy; }
set { SetProperty(ref _lockedBy, value); }
}
private DateTime _lockDate = new DateTime(0);
[DataMember]
public DateTime LockDate {
get { return _lockDate; }
set { SetProperty(ref _lockDate, value); }
}
private bool _isDeleted = false;
[DataMember]
public bool IsDeleted {
get { return _isDeleted; }
set { SetProperty(ref _isDeleted, value); }
}
#endregion Properties
#region Initialization
public DatabaseTraits() : base() {
/*makes sure my overriden RegisterProperties() is called.*/
}
protected override void RegisterProperties() {
RegisterProperty(ref _id, "Id");
RegisterProperty(ref _isLocked, "IsLocked");
RegisterProperty(ref _lockedBy, "LockedBy");
RegisterProperty(ref _lockDate, "LockDate");
RegisterProperty(ref _isDeleted, "IsDeleted");
}
#endregion Initialization
#region Methods
public void Copy(DatabaseTraits that) {
Id = that.Id;
IsLocked = that.IsLocked;
LockedBy = that.LockedBy;
LockDate = that.LockDate;
IsDeleted = that.IsDeleted;
}
#endregion Methods
}
Về mặt kỹ thuật, 'age' là một thành viên riêng tư, do đó sẽ không biên dịch được. Nó sẽ cần phải được 'công khai', vv để làm việc. –
Xin lỗi, tôi đã không nhận ra điều đó. Nhưng đó chỉ là để làm rõ câu hỏi của tôi. –
Nếu bạn không chỉ rõ ': base (...)' và ': this (...)' cho một hàm tạo non-static, mặc định là ': base()' nghĩa là hàm tạo lớp cơ sở zero-parameter. Bạn cũng có với lớp đầu tiên 'Person' trong đó hàm tạo' Person() 'của bạn ngầm gọi phương thức khởi tạo của lớp cơ sở' Object() '. Viết ': base()' (đối số bằng không) luôn luôn thừa. Ngoài ra, hãy thử lại ví dụ của bạn khi hàm tạo lớp 'Person' nhận một hoặc nhiều tham số. –