INotifyPropertyChanged의 실현에 대해 이야기하다
5183 단어 property
일반적인 실현 방식
이것은 다음과 같은 일반적인 실현 방식이다.
public class NotifyPropertyChanged : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
virtual internal protected void OnPropertyChanged(string propertyName) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
이러한 방식을 일반적인 실현 방식이라고 부른다. 왜냐하면 이것은 정말 너무 일반적이기 때문에 사용하기에도 혐오감을 느낀다. 왜냐하면 수동으로 속성 이름을 지정해야 하기 때문이다.
public class MyViewModel : NotifyPropertyChanged {
private int _myField;
public int MyProperty {
get { return _myField; }
set {
_myField = value;
OnPropertyChanged("MyProperty");
}
}
}
lambda 표현식 실현 방식
lambda 표현식에 익숙한 학생들은 lambda 표현식으로 속성 이름 전달을 실현하고 NotifyPropertyChanged 클래스에 이런 방법을 추가하는 것을 고려할 수 있다.
protected void SetProperty<T>(ref T propField, T value, Expression<Func<T>> expr) {
var bodyExpr = expr.Body as System.Linq.Expressions.MemberExpression;
if (bodyExpr == null) {
throw new ArgumentException("Expression must be a MemberExpression!", "expr");
}
var propInfo = bodyExpr.Member as PropertyInfo;
if (propInfo == null) {
throw new ArgumentException("Expression must be a PropertyExpression!", "expr");
}
var propName = propInfo.Name;
propField = value;
this.OnPropertyChanged(propName);
}
Notify Property Changed 기본 클래스를 사용하면 다음과 같은 이점을 얻을 수 있습니다.
public class MyViewModel : NotifyPropertyChanged {
private int _myField;
public int MyProperty {
get { return _myField; }
set {
base.SetProperty(ref _myField, value, () => this.MyProperty);
}
}
}
이렇게 되면 속성 명칭을 문자열로 전달하는 것을 lambda 표현식으로 전달하는 것으로 바꾸어 하드코딩을 줄였기 때문에 확실히 많이 편리해졌지만 그래도 약간 번거로움을 느꼈다. 그래도 lambda 표현식을 써서 속성 명칭을 전달해야 한다.
차단 방식 실현
Castal에 대해DynamicProxy가 인상적이라면 DynamicProxy를 사용하여 차단하는 것을 고려할 수 있습니다. 제 실현은 다음과 같습니다.
// 1. , PostProcess , set_ ,
// , 。
internal class NotifyPropertyChangedInterceptor : StandardInterceptor {
protected override void PostProceed(IInvocation invocation) {
base.PostProceed(invocation);
var methodName = invocation.Method.Name;
if (methodName.StartsWith("set_")) {
var propertyName = methodName.Substring(4);
var target = invocation.Proxy as NotifyPropertyChanged;
if (target != null) {
target.OnPropertyChanged(propertyName);
}
}
}
}
// 2. , 。
public static class ViewModelHelper {
private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator();
private static readonly NotifyPropertyChangedInterceptor Interceptor
= new NotifyPropertyChangedInterceptor();
public static T CreateProxy<T>(T obj) where T : class, INotifyPropertyChanged {
return ProxyGenerator.CreateClassProxyWithTarget(obj, Interceptor);
}
}
사용하기 쉽지만 ViewModel 객체를 만들 때는 다음과 같은 도움말 클래스를 사용하여 인스턴스를 만들어야 합니다.
public class MyViewModel : NotifyPropertyChanged {
// , 。
public int MyProperty {
get; set;
}
}
// :
var viewModel = ViewModelHelper.CreateProxy<MyViewModel>();
viewModel.MyProperty = 100;
그러나 이러한 실현의 단점은 모든 속성이PropertyChanged 이벤트를 촉발할 수 있고 하나의 이벤트만 촉발할 수 있다는 것이다. 실제 개발에서 간혹 하나의 속성을 설정하여 여러 개의PropertyChanged 이벤트를 촉발해야 한다.
미래.Net 4.5 구현 방법
곧 발표될 예정입니다.Net 4.5는 4CallerMemberNameAttribute태그, 이 속성을 이용하여 위에서 제공한 SetProperty 방법을 개조할 수 있습니다. 이런 실현이야말로 가장 완벽한 것입니다.
protected void SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) {
if (object.Equals(storage, value)) return;
storage = value;
this.OnPropertyChanged(propertyName);
}
Caller MemberName 태그 지원이 있으므로 사용하기 편리합니다.
public class MyViewModel : NotifyPropertyChanged {
private int _myField;
public int MyProperty {
get { return _myField; }
set {
base.SetProperty(ref _myField, value);
}
}
}
이런 방법은 비록 좋지만, 오직 있을 뿐이다.Net 4.5에는 없으며 Silverlight에 추가되지 않을 수도 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python 특수 속성property 원리 및 사용 방법 분석1 특성 속성 property는 특수한 속성입니다. 접근할 때 기능 (함수) 을 실행하고 값을 되돌려줍니다. 주의: 이 때의 특성arear와perimeter는 값을 부여할 수 없습니다 2 왜 프로퍼티를 써? 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.