/* * EventBindingService.cs - handles binding of Control events to CodeBehind methods * * Authors: * Michael Hutchinson * * Copyright (C) 2005 Michael Hutchinson * * This sourcecode is licenced under The MIT License: * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; using System.CodeDom; using System.ComponentModel.Design; using System.ComponentModel; using System.Collections; using System.Reflection; using System.Globalization; namespace WinFormsAddin { public class EventBindingService : IEventBindingService { MonoDevelopProxy proxy; public EventBindingService (MonoDevelopProxy proxy) { this.proxy = proxy; } #region IEventBindingService Members public string CreateUniqueMethodName (IComponent component, EventDescriptor e) { if (component.Site == null || component.Site.Name == null) throw new ArgumentException ("IComponent must be sited and named"); //TODO: check component.Site.Name is valid as start of method name string trialPrefix = component.Site.Name + "_" + e.Name; return proxy.GenerateIdentifierUniqueInCodeBehind (trialPrefix); } public System.Collections.ICollection GetCompatibleMethods (System.ComponentModel.EventDescriptor e) { MethodInfo mi = e.EventType.GetMethod ("Invoke"); CodeMemberMethod methodSignature = MonoDevelop.DesignerSupport.BindingService.ReflectionToCodeDomMethod (mi); return proxy.GetCompatibleMethodsInCodeBehind (methodSignature); } public System.ComponentModel.EventDescriptor GetEvent (System.ComponentModel.PropertyDescriptor property) { EventPropertyDescriptor epd = property as EventPropertyDescriptor; if (epd == null) return null; return epd.InternalEventDescriptor; } public System.ComponentModel.PropertyDescriptorCollection GetEventProperties (System.ComponentModel.EventDescriptorCollection events) { ArrayList props = new ArrayList (); foreach (EventDescriptor e in events) props.Add (GetEventProperty (e)); return new PropertyDescriptorCollection ((PropertyDescriptor[]) props.ToArray (typeof (PropertyDescriptor))); } public System.ComponentModel.PropertyDescriptor GetEventProperty (System.ComponentModel.EventDescriptor e) { if (e == null) throw new ArgumentNullException ("e"); return new EventPropertyDescriptor (e); } public bool ShowCode (System.ComponentModel.IComponent component, System.ComponentModel.EventDescriptor e) { PropertyDescriptor pd = GetEventProperty (e); string name = (string) pd.GetValue (component); if (name == null) { name = CreateUniqueMethodName (component, e); pd.SetValue (component, name); } MethodInfo mi = e.EventType.GetMethod ("Invoke"); CodeMemberMethod methodSignature = MonoDevelop.DesignerSupport.BindingService.ReflectionToCodeDomMethod (mi); methodSignature.Name = name; methodSignature.Attributes = MemberAttributes.Family; return proxy.ShowMethod (methodSignature); } public bool ShowCode (int lineNumber) { return proxy.ShowLine (lineNumber); } public bool ShowCode () { return ShowCode (0); } #endregion } internal class EventPropertyDescriptor : PropertyDescriptor { private EventDescriptor eDesc; private TypeConverter tc; public EventPropertyDescriptor (EventDescriptor eDesc) : base (eDesc) { this.eDesc = eDesc; } public override bool CanResetValue (object component) { return true; } public override Type ComponentType { get { return eDesc.ComponentType; } } public override object GetValue(object component) { IDictionaryService dict = GetDictionaryService (component); return dict.GetValue (base.Name) as string; } public override bool IsReadOnly { get { return false; } } public override Type PropertyType { get { return eDesc.EventType; } } public override void ResetValue (object component) { SetValue (component, null); } public override void SetValue (object component, object value) { IDictionaryService dict = GetDictionaryService (component); dict.SetValue (base.Name, value); } public override bool ShouldSerializeValue (object component) { if (GetValue (component) == null) return false; return true; } internal static IDictionaryService GetDictionaryService (object component) { if (component == null) throw new ArgumentNullException ("component"); IComponent comp = component as IComponent; if (comp == null || comp.Site == null) throw new ArgumentException ("component must be a sited IComponent", "component"); IDictionaryService dict = comp.Site.GetService (typeof (IDictionaryService)) as IDictionaryService; if (dict == null) throw new InvalidOperationException ("could not obtain IDictionaryService implementation"); return dict; } public override TypeConverter Converter { get { if (tc == null) tc = TypeDescriptor.GetConverter (string.Empty); return tc; } } internal EventDescriptor InternalEventDescriptor { get { return eDesc; } } } }