- Timestamp:
- 11/15/10 09:41:51 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ParameterBinding/HeuristicLab.Core/3.3/ItemBinding.cs
r4788 r4790 7 7 using System.Reflection; 8 8 using System.Reflection.Emit; 9 using System.ComponentModel; 10 using System.Linq.Expressions; 9 11 10 12 namespace HeuristicLab.Core { … … 22 24 [Storable] 23 25 private bool bound; 24 26 [Storable] 27 private LambdaExpression bindingExpression; 28 29 private Delegate bindingFunc; 25 30 private static object evhCacheLock = new object(); 26 31 private static Dictionary<Type, DynamicMethod> eventHandlerCache = new Dictionary<Type, DynamicMethod>(); … … 33 38 this.source = cloner.Clone(original.source); 34 39 this.sourcePath = original.sourcePath; 40 this.bindingExpression = original.bindingExpression; 41 if (this.bindingExpression != null) 42 this.bindingFunc = this.bindingExpression.Compile(); 35 43 if (original.bound) Bind(); 36 44 } … … 42 50 this.bound = false; 43 51 } 52 public ItemBinding(IDeepCloneable target, string targetPath, IDeepCloneable source, string sourcePath, LambdaExpression func) 53 : this(target, targetPath, source, sourcePath) { 54 this.bindingExpression = func; 55 this.bindingFunc = this.bindingExpression.Compile(); 56 } 44 57 45 58 public IDeepCloneable Clone(Cloner cloner) { … … 54 67 private void AfterDeserialization() { 55 68 if (bound) RegisterEventHandlers(); 69 if (bindingExpression != null) 70 bindingFunc = bindingExpression.Compile(); 56 71 } 57 72 … … 71 86 object current = source; 72 87 foreach (string property in properties) { 73 TryHookToChangedEvent(current, property + "Changed");88 TryHookToChangedEvent(current, property); 74 89 MethodInfo mInfo = current.GetType().GetProperty(property, Flags).GetGetMethod(true); 75 90 object next = mInfo.Invoke(current, null); … … 83 98 object current = source; 84 99 foreach (string property in properties) { 85 TryUnhookFromChangedEvent(current, property + "Changed");100 TryUnhookFromChangedEvent(current, property); 86 101 MethodInfo mInfo = current.GetType().GetProperty(property, Flags).GetGetMethod(true); 87 102 object next = mInfo.Invoke(current, null); … … 95 110 string[] sourceProperties = sourcePath.Split('.'); 96 111 object cSource = source; 97 #region Navigate to source property 112 #region Navigate to source property (readd bindings if necessary) 98 113 bool reregister = false; 99 114 for (int i = 0; i < sourceProperties.Length; i++) { 100 115 if (cSource == null) return; 101 116 string property = sourceProperties[i]; 102 if (reregister) TryHookToChangedEvent(cSource, property + "Changed");117 if (reregister) TryHookToChangedEvent(cSource, property); 103 118 if (cSource == sender) reregister = true; 104 object next = cSource.GetType().GetProperty(property, Flags).GetGetMethod(true).Invoke(cSource, null); 119 PropertyInfo pInfo = cSource.GetType().GetProperty(property, Flags); 120 if (pInfo == null) return; 121 object next = pInfo.GetGetMethod(true).Invoke(cSource, null); 105 122 cSource = next; 106 123 } … … 112 129 #region Navigate to target property 113 130 for (int i = 0; i < targetProperties.Length - 1; i++) { 114 cTarget = cTarget.GetType().GetProperty(targetProperties[i], Flags).GetGetMethod(true).Invoke(cTarget, null); 131 PropertyInfo pInfo = cTarget.GetType().GetProperty(targetProperties[i], Flags); 132 if (pInfo == null) return; 133 cTarget = pInfo.GetGetMethod(true).Invoke(cTarget, null); 115 134 if (cTarget == null) return; 116 135 } … … 119 138 #endregion 120 139 121 if (cSource == null && !targetSetter.GetParameters().First().ParameterType.IsValueType 140 if (bindingFunc != null) { 141 targetSetter.Invoke(cTarget, new object[] { bindingFunc.DynamicInvoke(new object[] { cSource }) }); 142 } else if (cSource == null && !targetSetter.GetParameters().First().ParameterType.IsValueType 122 143 || cSource != null && cSource.GetType().IsValueType) 123 144 targetSetter.Invoke(cTarget, new object[] { cSource }); … … 128 149 129 150 private bool TryHookToChangedEvent(object obj, string property) { 130 EventInfo eInfo = obj.GetType().GetEvent(property, Flags); 131 if (eInfo != null) { 132 Type[] methodParams = eInfo.EventHandlerType.GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray(); 133 if (!eventHandlerCache.ContainsKey(methodParams[1])) 134 CreateAndAddDynamicEventHandler(eInfo, methodParams); 135 eInfo.AddEventHandler(obj, eventHandlerCache[methodParams[1]].CreateDelegate(eInfo.EventHandlerType, this)); 136 } 137 return eInfo != null; 151 INotifyPropertyChanged npc = (obj as INotifyPropertyChanged); 152 if (npc != null) { 153 npc.PropertyChanged += new PropertyChangedEventHandler(source_PropertyChanged); 154 return true; 155 } else { 156 EventInfo eInfo = obj.GetType().GetEvent(property + "Changed", Flags); 157 if (eInfo != null) { 158 Type[] methodParams = eInfo.EventHandlerType.GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray(); 159 if (!eventHandlerCache.ContainsKey(methodParams[1])) 160 CreateAndAddDynamicEventHandler(eInfo, methodParams); 161 eInfo.AddEventHandler(obj, eventHandlerCache[methodParams[1]].CreateDelegate(eInfo.EventHandlerType, this)); 162 } 163 return eInfo != null; 164 } 138 165 } 139 166 140 167 private bool TryUnhookFromChangedEvent(object obj, string property) { 141 EventInfo eInfo = obj.GetType().GetEvent(property, Flags); 142 if (eInfo != null) { 143 Type[] methodParams = eInfo.EventHandlerType.GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray(); 144 if (eventHandlerCache.ContainsKey(methodParams[1])) 145 eInfo.RemoveEventHandler(obj, eventHandlerCache[methodParams[1]].CreateDelegate(eInfo.EventHandlerType, this)); 146 } 147 return eInfo != null; 168 INotifyPropertyChanged npc = (obj as INotifyPropertyChanged); 169 if (npc != null) { 170 npc.PropertyChanged -= new PropertyChangedEventHandler(source_PropertyChanged); 171 return true; 172 } else { 173 EventInfo eInfo = obj.GetType().GetEvent(property, Flags); 174 if (eInfo != null) { 175 Type[] methodParams = eInfo.EventHandlerType.GetMethod("Invoke").GetParameters().Select(x => x.ParameterType).ToArray(); 176 if (eventHandlerCache.ContainsKey(methodParams[1])) 177 eInfo.RemoveEventHandler(obj, eventHandlerCache[methodParams[1]].CreateDelegate(eInfo.EventHandlerType, this)); 178 } 179 return eInfo != null; 180 } 181 } 182 183 private void source_PropertyChanged(object sender, PropertyChangedEventArgs e) { 184 ExecuteBinding(sender); 148 185 } 149 186 … … 152 189 if (!eventHandlerCache.ContainsKey(methodParams[1])) { 153 190 Type[] instanceMethodParams = new Type[] { GetType() }.Concat(methodParams).ToArray(); 154 DynamicMethod dynamicEventHandler = new DynamicMethod("source Changed", null, instanceMethodParams, GetType());191 DynamicMethod dynamicEventHandler = new DynamicMethod("source_Changed", null, instanceMethodParams, GetType()); 155 192 MethodInfo executeBindingMethodInfo = GetType().GetMethod("ExecuteBinding", Flags); 156 193 ILGenerator iLG = dynamicEventHandler.GetILGenerator();
Note: See TracChangeset
for help on using the changeset viewer.