/////////////////////////////////////////////////////////////////////////////// //File: Wrapper_WireupHelper.cs // //Description: A helper utility that emulates Decal.Adapter's automagic view // creation and control/event wireup with the MetaViewWrappers. A separate set // of attributes is used. // //References required: // Wrapper.cs // //This file is Copyright (c) 2010 VirindiPlugins // //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.Collections.Generic; using System.Text; using System.Reflection; #if METAVIEW_PUBLIC_NS namespace MetaViewWrappers #else namespace MyClasses.MetaViewWrappers #endif { #region Attribute Definitions [AttributeUsage(AttributeTargets.Class)] #if VVS_WRAPPERS_PUBLIC public #else internal #endif sealed class MVWireUpControlEventsAttribute : Attribute { public MVWireUpControlEventsAttribute() { } } [AttributeUsage(AttributeTargets.Field)] #if VVS_WRAPPERS_PUBLIC public #else internal #endif sealed class MVControlReferenceAttribute : Attribute { string ctrl; // Summary: // Construct a new ControlReference // // Parameters: // control: // Control to reference public MVControlReferenceAttribute(string control) { ctrl = control; } // Summary: // The Control Name public string Control { get { return ctrl; } } } [AttributeUsage(AttributeTargets.Field)] #if VVS_WRAPPERS_PUBLIC public #else internal #endif sealed class MVControlReferenceArrayAttribute : Attribute { private System.Collections.ObjectModel.Collection myControls; /// /// Constructs a new ControlReference array /// /// Names of the controls to put in the array public MVControlReferenceArrayAttribute(params string[] controls) : base() { this.myControls = new System.Collections.ObjectModel.Collection(controls); } /// /// Control collection /// public System.Collections.ObjectModel.Collection Controls { get { return this.myControls; } } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] #if VVS_WRAPPERS_PUBLIC public #else internal #endif sealed class MVViewAttribute : Attribute { string res; // Summary: // Constructs a new view from the specified resource // // Parameters: // Resource: // Embedded resource path public MVViewAttribute(string resource) { res = resource; } // Summary: // The resource to load public string Resource { get { return res; } } } [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] #if VVS_WRAPPERS_PUBLIC public #else internal #endif sealed class MVControlEventAttribute : Attribute { string c; string e; // Summary: // Constructs the ControlEvent // // Parameters: // control: // Control Name // // controlEvent: // Event to Wire public MVControlEventAttribute(string control, string eventName) { c = control; e = eventName; } // Summary: // Control Name public string Control { get { return c; } } // // Summary: // Event to Wire public string EventName { get { return e; } } } #endregion Attribute Definitions #if VVS_WRAPPERS_PUBLIC public #else internal #endif static class MVWireupHelper { private class ViewObjectInfo { public List Views = new List(); } static Dictionary VInfo = new Dictionary(); public static MyClasses.MetaViewWrappers.IView GetDefaultView(object ViewObj) { if (!VInfo.ContainsKey(ViewObj)) return null; if (VInfo[ViewObj].Views.Count == 0) return null; return VInfo[ViewObj].Views[0]; } public static void WireupStart(object ViewObj, Decal.Adapter.Wrappers.PluginHost Host) { if (VInfo.ContainsKey(ViewObj)) WireupEnd(ViewObj); ViewObjectInfo info = new ViewObjectInfo(); VInfo[ViewObj] = info; Type ObjType = ViewObj.GetType(); //Start views object[] viewattrs = ObjType.GetCustomAttributes(typeof(MVViewAttribute), true); foreach (MVViewAttribute a in viewattrs) { info.Views.Add(MyClasses.MetaViewWrappers.ViewSystemSelector.CreateViewResource(Host, a.Resource)); } //Wire up control references foreach (FieldInfo fi in ObjType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) { if (Attribute.IsDefined(fi, typeof(MVControlReferenceAttribute))) { MVControlReferenceAttribute attr = (MVControlReferenceAttribute)Attribute.GetCustomAttribute(fi, typeof(MVControlReferenceAttribute)); MetaViewWrappers.IControl mycontrol = null; //Try each view foreach (MyClasses.MetaViewWrappers.IView v in info.Views) { try { mycontrol = v[attr.Control]; } catch { } if (mycontrol != null) break; } if (mycontrol == null) throw new Exception("Invalid control reference \"" + attr.Control + "\""); if (!fi.FieldType.IsAssignableFrom(mycontrol.GetType())) throw new Exception("Control reference \"" + attr.Control + "\" is of wrong type"); fi.SetValue(ViewObj, mycontrol); } else if (Attribute.IsDefined(fi, typeof(MVControlReferenceArrayAttribute))) { MVControlReferenceArrayAttribute attr = (MVControlReferenceArrayAttribute)Attribute.GetCustomAttribute(fi, typeof(MVControlReferenceArrayAttribute)); //Only do the first view if (info.Views.Count == 0) throw new Exception("No views to which a control reference can attach"); Array controls = Array.CreateInstance(fi.FieldType.GetElementType(), attr.Controls.Count); IView view = info.Views[0]; for (int i = 0; i < attr.Controls.Count; ++i) { controls.SetValue(view[attr.Controls[i]], i); } fi.SetValue(ViewObj, controls); } } //Wire up events foreach (MethodInfo mi in ObjType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) { if (!Attribute.IsDefined(mi, typeof(MVControlEventAttribute))) continue; Attribute[] attrs = Attribute.GetCustomAttributes(mi, typeof(MVControlEventAttribute)); foreach (MVControlEventAttribute attr in attrs) { MetaViewWrappers.IControl mycontrol = null; //Try each view foreach (MyClasses.MetaViewWrappers.IView v in info.Views) { try { mycontrol = v[attr.Control]; } catch { } if (mycontrol != null) break; } if (mycontrol == null) throw new Exception("Invalid control reference \"" + attr.Control + "\""); EventInfo ei = mycontrol.GetType().GetEvent(attr.EventName); ei.AddEventHandler(mycontrol, Delegate.CreateDelegate(ei.EventHandlerType, ViewObj, mi.Name)); } } } public static void WireupEnd(object ViewObj) { if (!VInfo.ContainsKey(ViewObj)) return; foreach (MyClasses.MetaViewWrappers.IView v in VInfo[ViewObj].Views) v.Dispose(); VInfo.Remove(ViewObj); } } }