दिलचस्प पोस्ट
सरणी में कुंजी के लिए खोजें, पुनरावर्ती रूप से MySql: MyISAM बनाम Inno DB! स्ट्रिंग में प्रत्येक 2 तत्व डालने का पायथनिक तरीका LINQ: कोई भी बनाम सब नहीं है शून्य डाउनटाइम के साथ एएसपी। नेट अनुप्रयोग को कैसे लागू करें चेकस्टाइल कॉन्फ़िगरेशन से IntelliJ IDEA कोड प्रारूप गतिशील रूप से JavaScript का उपयोग करके शैली-वेबकिट-ट्रांसफॉर्म को सेट कैसे करें? फ़ंक्शन से आउटपुट के रूप में मैं चेतावनियों और त्रुटियों को कैसे बचा सकता हूं? क्या किसी दृश्य के क्लिक लक्ष्य के आकार को बढ़ाने के लिए एंड्रॉइड में एक टच डिलीगेट का उपयोग करने का एक उदाहरण है? Django फॉर्म में अनुरोध डेटा प्राप्त करें फायरबेज उपयोगकर्ता टेबल पर अतिरिक्त विवरण जोड़ें onMouseMove माउस स्थिति प्राप्त करें जावा में स्पष्ट अधिकतम लंबाई के बिना रेगेक्स लुक बैक ट्विटर बूटस्ट्रैप को कैसे नामित करें, तो शैलियों में संघर्ष नहीं होता Scanf के बाद सेफ़फ़ॉल्ट?

स्ट्रिंग नाम का उपयोग किए बिना संपदा-बदले गए ईवेंट को कैसे बढ़ाएं

परिवर्तित संपत्ति के नाम को स्पष्ट रूप से निर्दिष्ट किए बिना 'सम्पत्ति परिवर्तित' घटना को बढ़ाने की क्षमता होना अच्छा होगा। मैं ऐसा कुछ करना चाहूंगा:

public string MyString { get { return _myString; } set { ChangePropertyAndNotify<string>(val=>_myString=val, value); } } private void ChangePropertyAndNotify<T>(Action<T> setter, T value) { setter(value); PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(setter.Method.Name)); } } 

इस मामले में प्राप्त नाम लैम्ब्डा-विधि का एक नाम है: "<set_MyString> b__0"।

  1. क्या मुझे यकीन है, कि "<set_" और "> b__0" को छानने से क्या सही संपत्ति नाम हमेशा उपलब्ध होगा?
  2. क्या संपत्ति के बारे में सूचित करने के लिए कोई अन्य संपत्ति है?

धन्यवाद।

Solutions Collecting From Web of "स्ट्रिंग नाम का उपयोग किए बिना संपदा-बदले गए ईवेंट को कैसे बढ़ाएं"

C # 6 उत्तर जोड़ा गया

सी # 6 में (और वीबी के जो भी संस्करण विज़ुअल स्टूडियो 2015 के साथ आता है) हमारे पास ऑपरेटर नाम है जो पहले से कहीं ज्यादा आसान काम करता है। नीचे मेरे मूल उत्तर में, मैं "स्वयं-बदला" सूचनाओं के सामान्य मामले को संभालने के लिए सी # 5 सुविधा (कॉलर जानकारी विशेषताएँ) का उपयोग करता हूं nameof ऑपरेटर का उपयोग सभी मामलों में किया जा सकता है, और विशेष रूप से "संबंधित-संपत्ति-बदल" सूचना परिदृश्य में उपयोगी है।

सादगी के लिए, मुझे लगता है कि मैं सामान्य स्वयं-बदले गए नोटिफिकेशन के लिए कॉल करने वाला जानकारी विशेषता दृष्टिकोण रखता हूं। कम टाइपिंग का मतलब टाइपो और कॉपी / पेस्ट प्रेरित बगों के लिए कम संभावना है … यहाँ संकलक सुनिश्चित करता है कि आप एक वैध प्रकार / सदस्य / चर चुनते हैं, लेकिन यह सुनिश्चित नहीं करता कि आप सही एक चुनते हैं। इसके बाद संबंधित-संपत्ति परिवर्तन नोटिफिकेशन के लिए ऑपरेटर के नए nameof उपयोग करना सरल होता है। नीचे दिए गए उदाहरण कॉलर जानकारी विशेषताओं के एक प्रमुख व्यवहार को दर्शाता है … यदि पैरामीटर कॉलर द्वारा निर्दिष्ट किया गया है, तो कॉलर जानकारी पैरामीटर मूल्य के लिए प्रदान की जाती है, केवल जब पैरामीटर को छोड़ा जाता है कॉल करने वाला)।

यह भी देखने योग्य है कि nameof ऑपरेटर का उपयोग nameof घटना संचालकों द्वारा भी किया जा सकता है अब आप इवेंट में PropertyName तुलना कर सकते हैं (जो एक string ) nameof ऑपरेटर का उपयोग करके किसी विशेष प्रॉपर्टी के लिए, अधिक जादू स्ट्रिंग्स को नष्ट कर रहा है।

नाम के लिए संदर्भ जानकारी यहां: https://msdn.microsoft.com/en-us/library/dn986596.aspx

उदाहरण:

 public class Program { void Main() { var dm = new DataModel(); dm.PropertyChanged += propertyChangedHandler; } void propertyChangedHandler(object sender, PropertyChangedEventArgs args) { if (args.PropertyName == nameof(DataModel.NumberSquared)) { //do something spectacular } } } public class DataModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { var e = new PropertyChangedEventArgs(propertyName); handler(this, e); } } } public class DataModel : DataModelBase { //a simple property string _something; public string Something { get { return _something; } set { _something = value; OnPropertyChanged(); } } //a property with another related property int _number; public int Number { get { return _number; } set { _number = value; OnPropertyChanged(); OnPropertyChanged(nameof(this.NumberSquared)); } } //a related property public int NumberSquared { get { return Number * Number; } } } 

मूल सी # 5 जवाब

सी # 5 के बाद से, कॉलर जानकारी विशेषताओं का उपयोग करने के लिए सबसे अच्छा, यह संकलन समय पर हल किया गया है, कोई प्रतिबिंब आवश्यक नहीं है

मैं इसे एक बेस क्लास में कार्यान्वित करता हूं, व्युत्पन्न कक्षाएं केवल अपनी संपत्ति सेटर्स के भीतर से OnPropertyChanged विधि को कॉल करते हैं। अगर कुछ प्रॉपर्टी दूसरे मूल्य में बदलाव करती है, तो मैं संपत्ति सेटर में भी "स्पष्ट" संस्करण का उपयोग कर सकता हूं, जो अब "सुरक्षित" नहीं है, लेकिन एक दुर्लभ स्थिति है जिसे मैं स्वीकार करता हूं।

वैकल्पिक रूप से आप इस पद्धति को स्वयं परिवर्तन नोटिफिकेशन के लिए इस्तेमाल कर सकते हैं, और संबंधित संपत्ति परिवर्तन अधिसूचनाओं के लिए @जहॉफ़ द्वारा दिए गए उत्तर का उपयोग कर सकते हैं … इसमें किसी भी जादू स्ट्रिंग का लाभ नहीं होगा, जिसमें स्वयं परिवर्तन नोटिफिकेशन के सामान्य मामले के लिए सबसे तेज़ निष्पादन होगा।

यह नवीनतम सुझाव नीचे लागू किया गया है (मुझे लगता है कि मैं इसका उपयोग शुरू कर दूँगा!)

 public class DataModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { OnPropertyChangedExplicit(propertyName); } protected void OnPropertyChanged<TProperty>(Expression<Func<TProperty>> projection) { var memberExpression = (MemberExpression)projection.Body; OnPropertyChangedExplicit(memberExpression.Member.Name); } void OnPropertyChangedExplicit(string propertyName) { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { var e = new PropertyChangedEventArgs(propertyName); handler(this, e); } } } public class DataModel : DataModelBase { //a simple property string _something; public string Something { get { return _something; } set { _something = value; OnPropertyChanged(); } } //a property with another related property int _number; public int Number { get { return _number; } set { _number = value; OnPropertyChanged(); OnPropertyChanged(() => NumberSquared); } } //a related property public int NumberSquared { get { return Number * Number; } } } 

अपडेट : मूल कोड विंडोज फोन के अनुकूल नहीं है, क्योंकि यह लैम्बेएक्सप्रेस.कंपाइल () पर आधारित होता है, जिससे ईवेंट स्रोत ऑब्जेक्ट प्राप्त होता है। यहां अपडेट की गई विस्तार विधि (साथ ही पैरामीटर चेक हटाए गए हैं):

  public static void Raise<T>(this PropertyChangedEventHandler handler, Expression<Func<T>> propertyExpression) { if (handler != null) { var body = propertyExpression.Body as MemberExpression; var expression = body.Expression as ConstantExpression; handler(expression.Value, new PropertyChangedEventArgs(body.Member.Name)); } } 

उपयोग नीचे के रूप में रहता है।


आप प्रॉपर्टी नाम प्राप्तकर्ता को कॉल करने वाले लैम्ब्डा फ़ंक्शन पर प्रतिबिंब का उपयोग कर प्राप्त कर सकते हैं। ध्यान दें कि आपको वास्तव में लैम्ब्डा को आमंत्रित करने की ज़रूरत नहीं है, आपको प्रतिबिंब के लिए इसकी आवश्यकता है:

 public static class INotifyPropertyChangedHelper { public static void Raise<T>(this PropertyChangedEventHandler handler, Expression<Func<T>> propertyExpression) { if (handler != null) { var body = propertyExpression.Body as MemberExpression; if (body == null) throw new ArgumentException("'propertyExpression' should be a member expression"); var expression = body.Expression as ConstantExpression; if (expression == null) throw new ArgumentException("'propertyExpression' body should be a constant expression"); object target = Expression.Lambda(expression).Compile().DynamicInvoke(); var e = new PropertyChangedEventArgs(body.Member.Name); handler(target, e); } } public static void Raise<T>(this PropertyChangedEventHandler handler, params Expression<Func<T>>[] propertyExpressions) { foreach (var propertyExpression in propertyExpressions) { handler.Raise<T>(propertyExpression); } } } 

यहां बताया गया है कि आप एक या कई संपत्तियों के लिए घटना को बढ़ाने के लिए अपने क्लास में उस सहायक का उपयोग कैसे कर सकते हैं:

 PropertyChanged.Raise(() => this.Now); PropertyChanged.Raise(() => this.Age, () => this.Weight); 

ध्यान दें कि इस सहायक को भी कोई संसद नहीं है, अगर PropertyChanged का null

निम्नलिखित उदाहरण में आपको 3 मान (बैकिंग फ़ील्ड, न्यू वैल्यू, लैम्ब्डा के रूप में संपत्ति) को पारित करना होगा, लेकिन कोई जादू स्ट्रिंग नहीं है और संपत्ति परिवर्तित होने की घटना केवल तब ही उठायी जाती है जब यह वास्तव में समान नहीं है।

 class Sample : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { this.SetProperty(ref _name, value, () => this.Name); } } protected void SetProperty<T>(ref T backingField, T newValue, Expression<Func<T>> propertyExpression) { if (backingField == null && newValue == null) { return; } if (backingField == null || !backingField.Equals(newValue)) { backingField = newValue; this.OnPropertyChanged(propertyExpression); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyExpression.GetPropertyName())); } } } 

और लैम्ब्डा अभिव्यक्ति से प्रॉपर्टी नाम प्राप्त करने के लिए निम्न कोड में विस्तार विधियां शामिल हैं।

 public static class Extensions { public static string GetPropertyName<TProperty>(this Expression<Func<TProperty>> propertyExpression) { return propertyExpression.Body.GetMemberExpression().GetPropertyName(); } public static string GetPropertyName(this MemberExpression memberExpression) { if (memberExpression == null) { return null; } if (memberExpression.Member.MemberType != MemberTypes.Property) { return null; } var child = memberExpression.Member.Name; var parent = GetPropertyName(memberExpression.Expression.GetMemberExpression()); if (parent == null) { return child; } else { return parent + "." + child; } } public static MemberExpression GetMemberExpression(this Expression expression) { var memberExpression = expression as MemberExpression; if (memberExpression != null) { return memberExpression; } var unaryExpression = expression as UnaryExpression; if (unaryExpression != null) { memberExpression = (MemberExpression)unaryExpression.Operand; if (memberExpression != null) { return memberExpression; } } return null; } public static void ShouldEqual<T>(this T actual, T expected, string name) { if (!Object.Equals(actual, expected)) { throw new Exception(String.Format("{0}: Expected <{1}> Actual <{2}>.", name, expected, actual)); } } } 

अंत में कुछ परीक्षण कोड:

 class q3191536 { public static void Test() { var sample = new Sample(); var propertyChanged = 0; sample.PropertyChanged += new PropertyChangedEventHandler((sender, e) => { if (e.PropertyName == "Name") { propertyChanged += 1; } } ); sample.Name = "Budda"; sample.Name.ShouldEqual("Budda", "sample.Name"); propertyChanged.ShouldEqual(1, "propertyChanged"); sample.Name = "Tim"; sample.Name.ShouldEqual("Tim", sample.Name); propertyChanged.ShouldEqual(2, "propertyChanged"); sample.Name = "Tim"; sample.Name.ShouldEqual("Tim", sample.Name); propertyChanged.ShouldEqual(2, "propertyChanged"); } } 

मैं एक्सटेंशन विधि का उपयोग कर रहा हूँ

 public static class ExpressionExtensions { public static string PropertyName<TProperty>(this Expression<Func<TProperty>> projection) { var memberExpression = (MemberExpression)projection.Body; return memberExpression.Member.Name; } } 

निम्नलिखित विधि के साथ संयोजन में विधि में परिभाषित किया गया है जो INotifyPropertyChanged इंटरफ़ेस (आमतौर पर एक आधार वर्ग जिसमें से मेरी अन्य कक्षाएं प्राप्त होती हैं) को लागू करता है।

 protected void OnPropertyChanged<TProperty>(Expression<Func<TProperty>> projection) { var e = new PropertyChangedEventArgs(projection.PropertyName()); OnPropertyChanged(e); } 

तो मैं निम्नानुसार संपत्ति बदलकर-ईवेंट बढ़ा सकता हूं

 private double _rate; public double Rate { get { return _rate; } set { if (_rate != value) { _rate = value; OnPropertyChanged(() => Rate ); } } } 

इस दृष्टिकोण का उपयोग करना, गुणों का नाम बदलने में आसान (विजुअल स्टूडियो में), यह सुनिश्चित करता है कि इसी प्रकार से संपितिकृत कॉल को भी अपडेट किया गया है।

यह मुझे ऐसा करने के लिए मिला है:

 public abstract class ViewModel<T> : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public void RaisePropertyChanged(Expression<Func<T, object>> expression) { var propertyName = GetPropertyFromExpression(expression); this.OnPropertyChanged(propertyName); } public string GetPropertyFromExpression(System.Linq.Expressions.Expression expression) { if (expression == null) throw new ArgumentException("Getting property name form expression is not supported for this type."); var lamda = expression as LambdaExpression; if (lamda == null) throw new NotSupportedException("Getting property name form expression is not supported for this type."); var mbe = lamda.Body as MemberExpression; if (mbe != null) return mbe.Member.Name; var unary = lamda.Body as UnaryExpression; if (unary != null) { var member = unary.Operand as MemberExpression; if (member != null) return member.Member.Name; } throw new NotSupportedException("Getting property name form expression is not supported for this type."); } } 

संपत्ति के नाम का उपयोग किए बिना ऐसा करने के कई तरीके हैं

बस ब्लॉग को पढ़ने के लिए सर्वश्रेष्ठ

http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/

http://justinangel.net/AutomagicallyImplementingINotifyPropertyChanged

पहले ही तैनात समाधान दो मुद्दों का मिश्रण है:
1) कुछ लोगों को आपको एक बेस क्लास बनाने और उसके पास से उत्तीर्ण करने की आवश्यकता होती है। यह एक बड़ी समस्या है जो आपकी कक्षा विरासत श्रृंखला में एक रिंच फेंक सकती है और आपको अपने डोमेन को फिर से डिजाइन करने के लिए इस तरह "अतिरिक्त" विकास की अनुमति देने के लिए प्रेरित कर सकता है
2) मौजूदा समाधान आपको एक लैम्ब्डा अभिव्यक्ति के माध्यम से बदला हुआ ईवेंट को आग लगाने के लिए कौन से प्रॉपर्टी को आग्रह करने की अनुमति देता है, फिर भी वे संपत्ति के नाम के स्ट्रिंग का प्रतिनिधित्व करते हैं और वितरित करते हैं क्योंकि वे मौजूदा प्रॉपर्टी चेंजएंडएआरएग्स क्लास पर भरोसा करते हैं। इसलिए वास्तव में कोई भी कोड जो आपके प्रॉपर्टी चेंजेड इवेंट का उपयोग करता है, फिर भी एक स्ट्रिंग तुलना करनी पड़ती है जो भविष्य में आपके द्वारा किए जाने वाले किसी भी स्वचालित रिफैक्टर को फिर से ब्रेक कर सकती है, न कि आपके संकलन का समर्थन करने का समय विंडो के बाहर है जो कि मुख्य बिंदुओं में से एक है पहली जगह में स्ट्रिंग्स के बजाय लैम्ब्डा एक्सप्रेशंस

यह मेरा जेनेरिक संस्करण है जो एमएस द्वारा शुरू की गई एक ही घटना / प्रतिनिधि पैटर्न का पालन करता है जिसका अर्थ है कोई आधार वर्ग नहीं और कोई विस्तार विधियां आवश्यक नहीं हैं।

 public class PropertyChangedEventArgs<TObject> : EventArgs { private readonly MemberInfo _property; public PropertyChangedEventArgs(Expression<Func<TObject, object>> expression) { _property = GetPropertyMember(expression); } private MemberInfo GetPropertyMember(LambdaExpression p) { MemberExpression memberExpression; if (p.Body is UnaryExpression) { UnaryExpression ue = (UnaryExpression)p.Body; memberExpression = (MemberExpression)ue.Operand; } else { memberExpression = (MemberExpression)p.Body; } return (PropertyInfo)(memberExpression).Member; } public virtual bool HasChanged(Expression<Func<TObject, object>> expression) { if (GetPropertyMember(expression) == Property) return true; return false; } public virtual MemberInfo Property { get { return _property; } } } public delegate void PropertyChangedEventHandler<TObject>(object sender, PropertyChangedEventArgs<TObject> e); public interface INotifyPropertyChanged<TObject> { event PropertyChangedEventHandler<TObject> PropertyChanged; } 

अब आप इसे इस तरह एक वर्ग पर उपयोग कर सकते हैं:

 public class PagedProduct : INotifyPropertyChanged<PagedProduct> { IPager _pager; public event PropertyChangedEventHandler<PagedProduct> PropertyChanged = delegate { }; public PagedProduct() { } public IPager Pager { get { return _pager; } set { if (value != _pager) { _pager = value; // let everyone know this property has changed. PropertyChanged(this, new PropertyChangedEventArgs<PagedProduct>(a => a.Pager)); } } } } 

और अंत में आप उस ऑब्जेक्ट की घटनाओं को सुन सकते हैं और यह निर्धारित कर सकते हैं कि लैम्ब्डा की अभिव्यक्ति का उपयोग करके कौन से संपत्ति बदल गई है!

 void SomeMethod() { PagedProduct pagedProducts = new PagedProduct(); pagedProducts.PropertyChanged += pagedProducts_PropertyChanged; } void pagedProducts_PropertyChanged(object sender, PropertyChangedEventArgs<PagedProduct> e) { // lambda expression is used to determine if the property we are interested in has changed. no strings here if (e.HasChanged(a => a.Pager)) { // do something mind blowing like ordering pizza with a coupon } } 

मैं जादुई तारों के साथ समस्याओं से बचने के लिए संपत्ति नाम प्राप्त करने के लिए एक सरल एक्सटेंशन विधि का उपयोग करता हूं यह कोड की पठनीयता भी रखता है, यानी यह स्पष्ट है कि क्या हो रहा है।

एक्सटेंशन विधि इस प्रकार है:

 public static string GetPropertyName(this MethodBase methodBase) { return methodBase.Name.Substring(4); } 

इसके साथ इसका मतलब है कि आप संपत्ति सेट नाम परिवर्तनों के खिलाफ लचीले हैं और निम्न की तरह दिखते हैं:

 private string _name; public string Name { get { return _name; } set { name = value; RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName()); } } 

मैंने यहां इस एक्सटेंशन विधि के बारे में अधिक लिखा है और मैंने यहां मिलान कोड स्निपेट प्रकाशित किया है I