venerdì 17 giugno 2011

State Object ?

In molti casi salta fuori questo spelndido concetto che però sembra applicabile a pochi contesti, anche se scondo me si può estendere/astrarre.

Il caso pratico è di mantenere lo stato di un oggetto in modo da poter accedere al suo contenuto di modificarlo e di renderlo fruibile a vari oggetti.

Questo deve in ogni modo essere "immutabile" anche se vedremo che un senso "molto" lato del concetto stesso.

class DataAnchor
{
private string _entryValue = "";
private int _entryStatus = 0;

public string entryValue
{
get { return _entryValue; }
set { _entryValue = value; }
}

public int entryStatus
{
get { return _entryStatus; }
set { _entryStatus = value; }
}
}

class StateObject
{
public static DataAnchor Anchor = new DataAnchor();
}



Letto il codice non è difficile comprendere che lo StateObject è una classe che banalmente espone come propietà statica l'oggetto che ci servirà.

Ora parlando per astrazione è possibile contestualizzare quest'esempio

class useState
{
public useState()
{
StateObject.Anchor.entryValue = "Inzio";
}

public void doSample()
{
Thread t1 = new Thread(StepA);
Thread t2 = new Thread(StepB);

t1.Start();

while (StateObject.Anchor.entryStatus != 1)
{
t2.Start();
break;
}
}

private void StepA()
{
StateObject.Anchor.entryValue = "StepA";
StateObject.Anchor.entryStatus = 1;
Console.WriteLine("t1..done");
}

private void StepB()
{
StateObject.Anchor.entryValue = "StepB";
StateObject.Anchor.entryStatus = 2;
Console.WriteLine("t2..done");
}
}


Benchè banale ... ( e ammetto anche fin troppo ) rende chiaro il concetto di stateObject.
In questo caso il processo esegue due tread che mutano lo stato del nostro state object e qualora i thread fossero n è possibile applicare una logica di concorrenzialità in modo che il primo dei due che porta l'oggetto a uno stato differente, può invocare il terzo thread..

martedì 14 giugno 2011

AutoCompleteExtender Framework 4

Vediamo se anche a voi è capitata la stessa cosa e non siete riusciti a risolverla ..
" cannot create page method "GetCompletationList" "

Questo controllo mi aveva dato problemi anche con la versione precedente non a caso avevo scritto un post che cercava di spiegare il funzionamento dell'extender... per un po' non l'ho utilizzato, ed ora che mi serve .. ha qualche problema .. per fortuna diverso da prima..

asp:TextBox
ID="txtContracts"
runat="server"
ClientIDMode="Static"
Text="start writing for search"
CssClass="contractField preSearch txtContracts"
Width="200px"

asp:AutoCompleteExtender
ID="acetxtContracts"
runat="server"
DelimiterCharacters=""
Enabled="True"
ServicePath=""
ServiceMethod="GetCompletionList"
MinimumPrefixLength="2"
TargetControlID="txtContracts"
UseContextKey="false"
CompletionInterval="500"

[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string[] GetCompletionList(string prefixText,int count)
{
return GetSuggestions(prefixText, count);
}

In questo modo va Sempre che l'autocomplete risieda nella pagina in cui c'e' il metodo...

martedì 7 giugno 2011

Generic De/Serializer

Tempo fa ( ora non ricordo ne come ne quando ) avevo pubblicato un breve articolo su come
implementare la serializzazione / deserializzazione di un file XML o dataTable sfruttando al
meglio quanto già disponibile nella libreria di Ms.

System.xml.serialization ci offre l' XmlSerializer. Ho utilizzato questa libreria in un sacco di
progetti ma non ho mai avuto il tempo di perfezionare il codice come e quanto avrei voluto.

Oggi qualche minuto da dedicarci l'ho trovato e mi sono sbizzarito con Generic, per ottenere
un Serializzatore e un Deserializzatore completamente custom.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace Utils.XmlHelpers
{
public static class XmlDeSerializerTool
{

public static void Serialize<T>(string fileName, T elements)
{
TextWriter tw = new StreamWriter(fileName);
XmlSerializer xmls = new XmlSerializer(typeof(T));
xmls.Serialize(tw, elements);

tw.Close();
tw = null;
xmls = null;
}

public static T Deserialize<T>(string fileName)
{
Type e = typeof(T);

T elements = (T)Activator.CreateInstance(e);

TextReader tr = new StreamReader(fileName);
XmlSerializer xmls = new XmlSerializer(typeof(T));

elements = (T)xmls.Deserialize(tr);

tr.Close();
tr = null;
xmls = null;

return elements;
}
}
}

forse c'e' da limare qualcosa nelle Using.. ma direi che non è il caso di fare dei sofismi.. eh eh !

Qualcuno disse ... "il limite è la fantasia.. nel mio caso a volte è il tempo.


giovedì 2 giugno 2011

Columns Custom Attribute e GridView

Nell'ottica di realizzare un modello di CRUD completamente dinamico linkato ai dati tramite List T mi sono imbattutto nel classico problema " già ma come associo un nome civile alle colonne di una dataTable?"

Ho fatto quindi qualche prova sfruttando i custom attribute, che si sono rivelati ottimi accessibili e per nulla complessi da usare. Certo è vero che come per tutte le cose esagerare non serve a rendere il proprio codice migliore, a volte lo rende più illegibile.

Partiamo quindi dalla classe CUSTOM ATTRIBUTE.


[
System.AttributeUsage(
AttributeTargets.Class|
AttributeTargets.Field |
AttributeTargets.Property,
AllowMultiple = true)
]
public class DbMapperAttribute:System.Attribute
{
private string _dbFieldName;
private string _mappingEntity;
private string _headerOrCaption;
private bool _isVisibile;
private int _columnOrder;

public string dbFieldName
{
get { return _dbFieldName; }
}

public string mappingEntity
{
get { return _mappingEntity; }
}

public string headrOrCaption
{
get { return _headerOrCaption; }
}

public int columnOrder
{
get { return _columnOrder; }
}

public bool isVisibile
{
get { return _isVisibile; }
}

public DbMapperAttribute(
int ColumnOrder,
string DbFieldName,
string MappingEntity,
string HeaderOrCaption,
bool IsVisible)
{
_dbFieldName = DbFieldName ;
_mappingEntity = MappingEntity;
_headerOrCaption = HeaderOrCaption;
_isVisibile = IsVisible;
_columnOrder = ColumnOrder;
}
}


System.AttributeUsage( AttributeTargets.Class| AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)

Di tutto quello che ho scritto questa è la cosa importante almeno quando lo è la using di
System.ComponentModel che quin non è menzionata.

Ora direi che è il momento di vedere l'entity e come questa subisce l'effetto
del custom Attribute.


[DbMapper(1,"IDEntita", "IDPrototipoEntita", "Id", true)]
[DbMapper(2,"NomeEntita", "NomePrototipoEntita", "Entit&agrave;",true)]
[DbMapper(3,"DescrizioneEntita", "DescrizionePrototipoEntita", "Descrizione",true)]
public class Entita
{
private int _IDEntita;
private string _NomeEntita;
private string _DescrizioneEntita;

public int IDEntita
{
get { return _IDEntita; }
set { _IDEntita = value; }
}
public string NomeEntita
{
get { return _NomeEntita; }
set { _NomeEntita = value;}
}
public string DescrizioneEntita
{
get { return _DescrizioneEntita; }
set { _DescrizioneEntita = value; }
}
}


E' importante che gli attributi vadano nell'intestazione della classe e non sulle singole proprietà
perchè e lo capiremo a breve, in questo modo sarà molto più semplice accedere agli attributi stessi.

Quindi posto di aver realizzato un proprio Generatore di colonne, pre DataBound (ossia
una sub che richiamerete prima ... )
All'interno è necessario implementare una logica non troppo differente da questa.

System.Attribute[] attrs = System.Attribute.GetCustomAttributes(modelPrototype);

foreach (System.Attribute attr in attrs)
{

if (attr is DbMapperAttribute)
{
DbMapperAttribute dma = (DbMapperAttribute)attr;

BoundField dcf = new BoundField();

dcf.HeaderText = dma.headrOrCaption;
dcf.DataField = dma.dbFieldName;
dcf.SortExpression = dma.dbFieldName;

grvItemsCollection.Columns.Add( dcf);
}
}

In questo modo sarete sempre sicuri di avere le vostre colonne ben Nominate.

Nell'esempio ho specificato altri parametri che possono dar vita e vigore alla fantasia di ogniuno di noi, come l'implementazione dell'ordine d'apparizione, oppure se visibile o no..

Verosimilmente non sarà complesso aggiungere anche il tipo

In questo modo sfruttando un unico controllo ( ben fatto e ben gestito ) si può sfruttare il codice
tante volte quante lo si vuole... !