Social Icons

jueves, 2 de febrero de 2012

Extendiendo, Overridando y Clases Base

Hace un par de días mi primo me preguntó sobre el significado de la palabra override. Intenté explicárselo con un par de ejemplos tontos y los dos sonaron bastante estúpidos… Bien, este es un ejemplo real.

Queremos crear web parts Silverlight y que todos ellos compartan las mismas propiedades básicas y el mismo método render. Así que extendiendo Microsoft.SharePoint.WebPartPages.WebPart crearemos un BaseSilverlightWebPart con estas características (overridando sí sí, has leído bien, overridando, nada de sobreescribiendo sobreescribir es irte a la clase base, borrar el metodo y escribir encimael método render de la clase WebPart) y después lo usaremos para crear otros web parts fácilmente.

La clase base quedó así:
  1. public abstract class BaseSilverlightWebpart : Microsoft.SharePoint.WebPartPages.WebPart  
  2. {  
  3.     #region Web Part Properties  
  4.     [Personalizable(PersonalizationScope.Shared)]  
  5.     [WebBrowsable(true)]  
  6.     [System.ComponentModel.Category("Stratex")]  
  7.     [WebDisplayName("XAP List URL")]  
  8.     [Description("Select the URL of the XAP list.")]  
  9.     public string XAPListUrl { getset; }  
  10.     #endregion  
  11.  
  12.     #region Private Properties  
  13.     Dictionary<stringstring> InitParams;  
  14.     #endregion  
  15.  
  16.     #region Abstract  
  17.     /// <summary>  
  18.     /// Setup here the of the XAP you will use  
  19.     /// </summary>  
  20.     public abstract string XAPName { get; }  
  21.   
  22.     /// <summary>  
  23.     /// Setup here the initial parameters you will use in your Silverlight Web Part  
  24.     /// </summary>  
  25.     public abstract void SetUpParameters();  
  26.     #endregion  
  27.  
  28.     #region Methods  
  29.     public void AddParameter(string Name, string Value)  
  30.     {  
  31.         if (InitParams == null)  
  32.             InitParams = new Dictionary<stringstring>();  
  33.   
  34.         if (InitParams.ContainsKey(Name))  
  35.             InitParams[Name] = Value;  
  36.         else  
  37.             InitParams.Add(Name, Value);  
  38.     }  
  39.     #endregion  
  40.  
  41.     #region Overrides  
  42.     protected override void CreateChildControls()  
  43.     {  
  44.         SetUpParameters();  
  45.   
  46.         if (string.IsNullOrEmpty(XAPListUrl))  
  47.             XAPListUrl = string.Format("{0}/Lists/XAPLibrary/", SPContext.Current.Web.ServerRelativeUrl);  
  48.   
  49.         //Sometimes when you create the web part it's 0px by 0px... ¬ ¬  
  50.         if (string.IsNullOrEmpty(Height)) Height = "150px";  
  51.         if (string.IsNullOrEmpty(Width)) Width = "150px";  
  52.   
  53.         LiteralControl obj = new LiteralControl();  
  54.         obj.Text = "<object id='silverlightHost' height='" + Height + "' width='" + Width +  
  55.             @"' data='data:application/x-silverlight-2,' type='application/x-silverlight-2' style='display:block' class='ms-dlgDisable'>  
  56.                         <param name='Source' value='" + XAPListUrl + XAPName + @"' />  
  57.                         <param name='MinRuntimeVersion' value='3.0.40624.0' />  
  58.                         <param name='Background' value='#00FFFFFF' />  
  59.                         <param name='windowless' value='true' />  
  60.                         <param name='autoUpgrade' value='true' />  
  61.                         ";  
  62.   
  63.         if (InitParams.Count > 0)  
  64.         {  
  65.             obj.Text +="<param name='initParams' value='";  
  66.   
  67.             int i = 0;  
  68.             foreach (var param in InitParams)  
  69.             {  
  70.                 if (i++ == 0)  
  71.                     obj.Text += string.Format("{0}={1}", param.Key, param.Value);  
  72.                 else  
  73.                     obj.Text += string.Format(", {0}={1}", param.Key, param.Value);  
  74.             }  
  75.   
  76.             obj.Text += @"' />  
  77.             ";  
  78.         }  
  79.         obj.Text += @"<a href='http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0' style='text-decoration: none;'>  
  80.             <img src='http://go.microsoft.com/fwlink/?LinkId=108181' alt='Click here to install Silverlight' style='border-style: none'/>  
  81.             </a>  
  82.             </object>";  
  83.   
  84.         this.Controls.Add(obj);  
  85.     }  
  86.     #endregion  
  87. }  
Extendiéndola podemos crear un web part Silverlight fácilmente:
  1. public class DynamicStrategyMap : BaseSilverlightWebpart  
  2. {  
  3.     #region Overrides  
  4.     public override string XAPName  
  5.     {  
  6.         get { return "StratexPointStrategyMap.xap"; }  
  7.     }  
  8.   
  9.     public override void SetUpParameters()  
  10.     {  
  11.         AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.ServerRelativeUrl));  
  12.     }  
  13.     #endregion  
  14. }  
Fíjate que no tienes que overridar ¿otra vez? nada si no te hace falta. El método render es exactamente igual que en la base por lo que no necesitamos ni nombrarlo. La clase usará el método de su clase base automáticamente. Mira cuánto código estamos ahorrándonos de escribir otra vez, todas las propiedades, el render gordo de la clase base, etc. Solo cambiamos lo que necesitamos cambiar.
También podemos añadir propiedades nuevas como aquí:
  1. public class StratexHeartBeat : BaseSilverlightWebpart  
  2. {  
  3.     #region WebPartProperties  
  4.     [Personalizable(PersonalizationScope.Shared)]  
  5.     [WebBrowsable(true)]  
  6.     [System.ComponentModel.Category("Stratex")]  
  7.     [WebDisplayName("NumberOfEvents")]  
  8.     public string NumberOfEvents { getset; }  
  9.   
  10.     [Personalizable(PersonalizationScope.Shared)]  
  11.     [WebBrowsable(true)]  
  12.     [System.ComponentModel.Category("Stratex")]  
  13.     [WebDisplayName("TimerLapse")]  
  14.     public string TimerLapse { getset; }  
  15.   
  16.     [Personalizable(PersonalizationScope.Shared)]  
  17.     [WebBrowsable(true)]  
  18.     [System.ComponentModel.Category("Stratex")]  
  19.     [WebDisplayName("Indicator Summary Url")]  
  20.     public string IndicatorSummaryUrl { getset; }  
  21.     #endregion  
  22.  
  23.     #region Overrides  
  24.   
  25.     public override string XAPName  
  26.     {  
  27.         get { return "StratexHeartBeat.xap"; }  
  28.     }  
  29.   
  30.     public override void SetUpParameters()  
  31.     {  
  32.         AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.Url));  
  33.   
  34.         if (string.IsNullOrEmpty(IndicatorSummaryUrl))  
  35.             IndicatorSummaryUrl = string.Format("{0}/Lists/WebPartPages/IndicatorSummary.aspx", SPContext.Current.Web.ServerRelativeUrl);  
  36.   
  37.         AddParameter("indicatorsummaryurl", IndicatorSummaryUrl);  
  38.   
  39.         if (Common.ConvertToInt(NumberOfEvents) < 1) NumberOfEvents = "1";  
  40.   
  41.         AddParameter("numberofnews", NumberOfEvents);  
  42.   
  43.         if (Common.ConvertToInt(TimerLapse) < 1) TimerLapse = "1";  
  44.   
  45.         AddParameter("timerlapse", TimerLapse);  
  46.     }  
  47.     #endregion  
  48. }  
O incluso podemos añadir más código al método render overridando el método render overridado en la clase base toma ya, doble tirabuzón, carpado y mortal hacia atrás de palabro inventado.
  1. public class Commentary : BaseSilverlightWebpart  
  2. {  
  3.     #region Overrides  
  4.     public override string XAPName  
  5.     {  
  6.         get { return "Commentary.xap"; }  
  7.     }  
  8.   
  9.     public override void SetUpParameters()  
  10.     {  
  11.         AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.ServerRelativeUrl));  
  12.     }  
  13.   
  14.     protected override void CreateChildControls()  
  15.     {  
  16.         base.CreateChildControls();  
  17.   
  18.         //We are using this code to be able to close the explorer window from Silverlight  
  19.         LiteralControl JavaScript = new LiteralControl();  
  20.   
  21.         JavaScript.Text = @"<script type='text/javascript'>  
  22.                             function doCloseLocal()   
  23.                             {  
  24.                                 var version = parseFloat(navigator.appVersion.split('MSIE')[1]);  
  25.   
  26.                                 if (version >= 7) {window.open('''_parent'''); }  
  27.   
  28.                                 else { window.opener = self;  }  
  29.   
  30.                                 window.close();  
  31.                             }  
  32.                             </script>";  
  33.         this.Controls.Add(JavaScript);  
  34.     }  
  35.  
  36.     #endregion  
  37. }  
Fíjate también que antes de añadir el nuevo control hemos llamado al render de la clase base para que el web part se renderice ¿otra? en la página.
Y esta es la pinta que tiene el override en la vida real. Ahora sí que tiene sentido… ¿o no?

No hay comentarios: