private static long TestCompiled() { DataTestForPerf src = new DataTestForPerf(); DataTestForPerf dst = new DataTestForPerf(); PropertyInfo piSource = src.GetType().GetProperty("Prop1"); PropertyInfo piDest = dst.GetType().GetProperty("Prop1"); GetHandlerDelegate <int> getSrc = GetSetUtils.CreateGetHandler <int>(piSource); SetHandlerDelegate <int> setDst = GetSetUtils.CreateSetHandler <int>(piDest); src.PropertyChanged += delegate { setDst(dst, getSrc(src)); }; Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 1; i <= NBTURNS; i++) { src.Prop1 = i; } watch.Stop(); return(watch.ElapsedMilliseconds); }
public void Bind(object source, PropertyInfo piSource, object destination, PropertyInfo piDest, IBinderConverter converter, SynchronizationContext applyBindingContext) { weakSrc = new WeakReference(source); weakDst = new WeakReference(destination); _Converter = converter; _PropNameSource = piSource.Name; _PropNameDest = piDest.Name; gethandler = GetSetUtils.CreateGetHandler <TValueSource>(piSource); //le set handler devrait être sur le type destination if (_Converter != null) { _CurrentChanged = OnValueChanged1; sethandlerDest = GetSetUtils.CreateSetHandler <TValueDest>(piDest); } else { _CurrentChanged = OnValueChanged; sethandler = GetSetUtils.CreateSetHandler <TValueSource>(piDest); } DataBinder.AddNotify <TValueSource>(source, piSource.Name, gethandler, _CurrentChanged, applyBindingContext); }
/// <summary> /// it for intermediate notifications, to rebind /// </summary> /// <param name="current">concerned object</param> /// <param name="pathitem">real property name</param> /// <param name="onchanged">delegate to call, when propertyname changed</param> private void AddNotify(object current, string pathitem, OnChangeDelegate <object> onchanged) { PropertyInfo pi = current.GetType().GetProperty(pathitem); GetHandlerDelegate <object> gethandler = GetSetUtils.CreateGetHandler <object>(pi); DataBinder.AddNotify <object>(current, pathitem, gethandler, onchanged, null); }
/// <summary> /// créée une méthode dynamique, pour lire le contenu d'une propriété sans utiliser la réflection /// </summary> /// <typeparam name="TValue"></typeparam> /// <typeparam name="TInstance"></typeparam> /// <param name="propertyInfo"></param> /// <returns></returns> public static GetHandlerDelegate <TValue> CreateGetHandler <TValue>(PropertyInfo propertyInfo) { MethodInfo getMethod = propertyInfo.GetGetMethod(true); if (_Dico.ContainsKey(getMethod)) { return((GetHandlerDelegate <TValue>)_Dico[getMethod]); } #if SILVERLIGHT ////it's work, but at runtime a SecurityException is thrown //DynamicMethod dynamicGet = new DynamicMethod("DynamicGet" + propertyInfo.Name, // typeof(TValue), // new Type[] { typeof(object) }); //it's not compiled, but it work GetHandlerDelegate <TValue> Result = delegate(object sender) { return((TValue)getMethod.Invoke(sender, null)); }; //ILGenerator getGenerator = dynamicGet.GetILGenerator(); //getGenerator.Emit(OpCodes.Ldarg_0); //getGenerator.Emit(OpCodes.Callvirt, getMethod); //getGenerator.Emit(OpCodes.Ret); //Type tDelegate = typeof(GetHandlerDelegate<TValue>); //GetHandlerDelegate<TValue> Result = (GetHandlerDelegate<TValue>)dynamicGet.CreateDelegate(tDelegate); #else DynamicMethod dynamicGet = new DynamicMethod("DynamicGet" + propertyInfo.Name, typeof(TValue), new Type[] { typeof(object) }, propertyInfo.DeclaringType, true); ILGenerator getGenerator = dynamicGet.GetILGenerator(); getGenerator.Emit(OpCodes.Ldarg_0); getGenerator.Emit(OpCodes.Call, getMethod); getGenerator.Emit(OpCodes.Ret); Type tDelegate = typeof(GetHandlerDelegate <TValue>); GetHandlerDelegate <TValue> Result = (GetHandlerDelegate <TValue>)dynamicGet.CreateDelegate(tDelegate); #endif _Dico[getMethod] = Result; return(Result); }
public OneNotify(GetHandlerDelegate <T> getter, OnChangeDelegate <T> onchanged) { _OnGet = getter; _OnChanged = onchanged; }
/// <summary> /// gestion de la notification sur INotifyPropertyChanged /// </summary> /// <typeparam name="T">type de la propriété observée</typeparam> /// <param name="source">source</param> /// <param name="propName">property à observer</param> /// <param name="gethandler">"get" a appeler a chaque changements</param> /// <param name="OnValueChange">la déléguée à appelée après chaque changed de la source</param> internal static void AddNotify <T>(object source, string propName, GetHandlerDelegate <T> gethandler, OnChangeDelegate <T> OnValueChange, SynchronizationContext applyBindingContext) { INotifyPropertyChanged inotify = source as INotifyPropertyChanged; if (inotify != null) { EqualityWeakReference weak = new EqualityWeakReference(inotify); //le but est ici de ne s'abonner qu'une fois Dictionary <string, IOneNotify> dico = null; if (!_SourceChanged.TryGetValue(weak, out dico)) { dico = new Dictionary <string, IOneNotify>(); _SourceChanged.Add(weak, dico); inotify.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { //je minimise le nombre de get, en founissant la valeur qui à changé if (dico.ContainsKey(e.PropertyName)) { dico[e.PropertyName].Fire(weak); } }; } ///plusieurs abonnement si nécessaire pour une propriété binding de 1 prop vers plusieurs dest OneNotify <T> binding = null; if (dico.ContainsKey(propName)) { binding = (OneNotify <T>)dico[propName]; binding._OnChanged = (OnChangeDelegate <T>)Delegate.Combine(binding._OnChanged, OnValueChange); } else { binding = new OneNotify <T>(gethandler, OnValueChange); binding._ApplyBindingContext = applyBindingContext; binding.PropertyName = propName; dico[propName] = binding; } } else if (source != null) { //try with old mode "PropertyName"Changed event string eventName = string.Format("{0}Changed", propName); EventInfo evInfo = source.GetType().GetEvent(eventName); if (evInfo != null) { EqualityWeakReference weak = new EqualityWeakReference(source); //le but est ici de ne s'abonner qu'une fois Dictionary <string, IOneNotify> dico = null; if (!_SourceChanged.TryGetValue(weak, out dico)) { dico = new Dictionary <string, IOneNotify>(); _SourceChanged.Add(weak, dico); } ///plusieurs abonnement si nécessaire pour une propriété binding de 1 prop vers plusieurs dest OneNotify <T> binding = null; if (dico.ContainsKey(propName)) { binding = (OneNotify <T>)dico[propName]; binding._OnChanged = (OnChangeDelegate <T>)Delegate.Combine(binding._OnChanged, OnValueChange); } else { binding = new OneNotify <T>(gethandler, OnValueChange); binding.PropertyName = propName; binding._ApplyBindingContext = applyBindingContext; binding._PropertyChangedEvent = delegate { binding.Fire(weak); }; dico[propName] = binding; evInfo.AddEventHandler(source, binding._PropertyChangedEvent); } } } }