giovedì 28 aprile 2011

"Ereditare" una classe Statica

Diciamo che per concetto è una cosa che non si può fare.

In questo esempio propongo un interessante workaround per poter ovviare alla potenziale "intenzione" di ereditare una classe statica.


public static class RealWriter
{
public static void Write(string text)
{
Console.WriteLine(text);
}
}

public class BaseWriter
{
public virtual void VirtualWrite(string text)
{
RealWriter.Write(text);
WriteToLog(text);
}

private void WriteToLog(string text)
{
TextWriter tw = new StreamWriter(@"c:\Logfile.txt",true);
tw.WriteLine(
DateTime.Now.ToShortDateString() + "|" +
DateTime.Now.ToShortTimeString() + "|" +
text
);
tw.Close();
}
}


public class LineWriter:BaseWriter
{
public override void VirtualWrite(string text)
{
base.VirtualWrite(text);
}
}


Qualche piccola delucidazione:



RealWriter è una classe statica "la cui provenienza potrebbe essere ignota" ossia una classe che proviene da un assembly esterno. Una reference per intenderci.

BaseWriter è nel nostro assembly, tecnicamente lo scopo di questa classe è di incapsulare/wrappare quanto è già stato realizzato per "eseguire delle altre cose in aggiunta"
In questo esempio il log...

LineWriter estende base writer in modo da non dover creare un legame troppo rigido con RealWriter.

L'esempio è decisamente banale e sono più che convinto che vi siano molti altri modi per rendere questa situazione.



public class BaseWriterDelegate
{
delegate void _RealWriter(string text);

_RealWriter handlersToRW;

public BaseWriterDelegate()
{
handlersToRW = WriteToConsole;
handlersToRW += WriteToLog;

}

public virtual void VirtualWrite(string text)
{
handlersToRW(text);
}

private void WriteToConsole(string text)
{
RealWriter.Write(text);
}

private void WriteToLog(string text)
{
TextWriter tw = new StreamWriter(@"c:\Logfile.txt", true);
tw.WriteLine(
DateTime.Now.ToShortDateString() + "|" +
DateTime.Now.ToShortTimeString() + "|" +
text
);
tw.Close();
}
}



public class LineWriter:BaseWriterDelegate
{
public override void VirtualWrite(string text)
{
base.VirtualWrite(text);
}
}


Si può anche far così ... volendo sfruttando i delegati, il discorso non cambia.

Di concetto rimane il fatto che il chiamante utilizzerà LineWriter senza aver percezione di ciò che avverà sotto!

mercoledì 27 aprile 2011

Abstract vs Virtual

Ma come sceglire quando usare una classe abstract o una classe con metodi virtual.

Vi posto questo esempio più o meno semplice per comprendere un filo meglio come
si comportano e le brevi differenze che ci possono essere fra l'una e l'altra.

public interface iTestClass
{
string ReturnMeString();
int ReturnMeInt();
string ReturnBasedString();
}


public class VirtualTest : iTestClass
{
public virtual string ReturnMeString()
{
return "virtual base ";
}

public virtual int ReturnMeInt()
{
return 0;
}

public virtual string ReturnBasedString()
{
return "virtual base ";
}
}



public abstract class AbstractTest :iTestClass
{
public abstract string ReturnMeString();

public abstract int ReturnMeInt();

public virtual string ReturnBasedString()
{
return "abstract base ";
}
}

public class ConcreteTest1 : AbstractTest
{

public override string ReturnMeString()
{
return "Concrete Test";
}

public override int ReturnMeInt()
{
return -1;
}

public override string ReturnBasedString()
{
return base.ReturnBasedString() + " New from concrete";
}
}

public class ConcreteTest2 : VirtualTest
{

public override string ReturnMeString()
{
return "Concrete Test";
}

public override int ReturnMeInt()
{
return -1;
}

public override string ReturnBasedString()
{
return base.ReturnBasedString() + " New from concrete";
}
}


public class testAll
{
public testAll()
{

}

public void DoTest()
{
iTestClass ct1 = new ConcreteTest1();

iTestClass ct2 = new ConcreteTest2();

Console.WriteLine("Ct1 String:" + ct1.ReturnMeString());
Console.WriteLine("Ct1 int:" + ct1.ReturnMeInt());
Console.WriteLine("Ct1 Base:" + ct1.ReturnBasedString());


Console.WriteLine("Ct2 String:" + ct2.ReturnMeString());
Console.WriteLine("Ct2 int:" + ct2.ReturnMeInt());
Console.WriteLine("Ct2 Base:" + ct2.ReturnBasedString());


Console.ReadLine();
}
}


Di certo e come sempre sta a noi individuare il contesto migliore per toglierci dai
guai o dai casini.

Thread.Yeld .Net 4

public class ThreadTester
{
Thread t1;
Thread t2;

private bool _StopJob = true;

public bool StopJob
{
get { return _StopJob; }
set { _StopJob = true; }
}

public ThreadTester()
{

}

public void StartMainJob()
{
t1 = new Thread(Process1);
t2 = new Thread(Process2);

t1.Start();
t2.Start();
}

public void Process1()
{
Console.WriteLine("t1:start");
int a = 0;

while (_StopJob)
{

a++;

if ((a % 100) == 0)
{
Console.WriteLine("t1:{0}", a);
Thread.Yield();
}


if ((a % 1000) == 0)
{
Console.WriteLine("t1:End");
_StopJob = false;
}
}
}

public void Process2()
{
Console.WriteLine("t2:start");
int b = 0;

while (_StopJob)
{

b++;

if ((b % 100) == 0)
{
Console.WriteLine("t2:{0}", b);
Thread.Yield();
}


if ((b % 1000) == 0)
{
Console.WriteLine("t2:End");
_StopJob = false;
}
}
}
}


In questo esempio mi sono prodigato nel comprendere questa novità del Framework 4.0 il Thread.Yield. Sulle prime non è mi stato molto chiaro come concetto ma proprio durante
la fase di debug salta fuori qualcosa di interessante che decisamente mi ha chiarificato il concetto.

Thread.Yield Restituisce true o false se il ns sistema operativo ha consentito ad un altro thread
di proseguire l'attività.

Il concetto di base, dovrebbe già aver logica nella programmazione a Thread, mentre uno e fermo l'altro prosegue nelle sue attività.

In debug fermando l'applicazione sul primo si ha piena evidenza del fatto che il secondo prosegua
serenamente le sue attività, rispetto al solito ... si ha in più la percezione che qualcuno "non si sa chi" ci abbia passato la palla per proseguire il lavoro.

Addio SwitchToThread ...

giovedì 7 aprile 2011

From DataTable To List T (entity)

Ho scritto post più recenti che danno maggiori informazioni sull'argomento :
how to: datatable to list
E:
how to: datatable to list solved


E' da un po che ronzo attorno a questo concetto ma non ho mai voluto perderci troppo tempo.http://www.blogger.com/img/blank.gif
Primo perchè per me una classe Entity (e relativa collection / list) è e rimane una classe da popolare tramite conversione da db pura "tramite data reader".
Secondo perchè ho sempre supposto una certa lentezza nell'uso di costrutti Generici applicati
ai dati.

Tuttavia mi sono un filo ricreduto dopo aver fatto questa prova, anche se non mi soddisfa del
tutto Ho ottenuto un buona sostanza un Cast da DataTable a List dove T è una classe
diversa da DataRow.

Certo è vero che il codice scritto è fonte di varie ispirazioni prelevate qua e la dal web, quello
che mi ha sorpreso è la velocità su un numero di elementi inferiore a 100, e la perdita di
presetazioni sopra 100000.

public class MagicTest
{

public class xDemo
{
public int demo0 { get; set; }
public int demo1 { get; set; }
public int demo2 { get; set; }
public string demo3 { get; set; }
public string demo4 { get; set; }
public string demo5 { get; set; }
}

public class Converter<T>
{
public List<T> ToList(DataTable dt)
{
List<T> gr = new List<T>();

Type t = typeof(T);

PropertyInfo[] _p = t.GetProperties();

foreach (DataRow r in dt.Rows)
{
object curIstance = Activator.CreateInstance(t);

foreach (PropertyInfo pr in _p)
{
try
{
object cValue = r[pr.Name];
if (cValue != DBNull.Value)
pr.SetValue(curIstance, cValue, null);
}
catch
{
return null;
}
}

T lOut = (T)curIstance;
gr.Add(lOut);
}

return gr;
}
}

public void doTest()
{

DataTable dtx = new DataTable();

dtx.Columns.Add("demo0", typeof(int));
dtx.Columns.Add("demo1", typeof(int));
dtx.Columns.Add("demo2", typeof(int));
dtx.Columns.Add("demo3", typeof(string));
dtx.Columns.Add("demo4", typeof(string));
dtx.Columns.Add("demo5", typeof(string));

for (int i = 0; i < 1000000; i++)
{
dtx.Rows.Add(new object[] { i, i*2, i*3, "A_"+ i.ToString(),"null","null"});
}

Converter<xDemo> cr = new Converter<xDemo>();


DateTime dsStart = DateTime.Now;
Console.WriteLine("start\t\t:" + dsStart.ToLongTimeString() + "." + dsStart.Millisecond.ToString().PadLeft(3, '0'));
List<xDemo> xD= cr.ToList(dtx);
DateTime dsEnd = DateTime.Now;
Console.WriteLine("end\t\t:" + dsEnd.ToLongTimeString() + "." + dsEnd.Millisecond.ToString().PadLeft(3, '0'));

TimeSpan ts = dsEnd - dsStart;
Console.WriteLine("total\t\t:" + ts.TotalMilliseconds.ToString());

}

}


E questi sono i miei risultati :

Case :10
start :12.24.34.459
end :12.24.34.484
total :24,9033

Case :100
start :12.27.56.234
end :12.27.56.258
total :23,9267

Case :1000
start :12.30.16.135
end :12.30.16.172
total :36,6225

Case :10000
start :12.33.53.492
end :12.33.53.649
total :156,256

Case :100000
start :12.34.32.124
end :12.34.33.572
total :1447,8095

Case :1000000
start :12.37.32.798
end :12.37.46.708
total :13910,2021


Soprattutto questi ultimi due ... mi fanno un po rilflettere.. ma su cifre comprese fra i 10000
e 50000 elementi la risposta non è male. Sarebbe carino testarlo su un db, o se qualcuno potesse
fare qualche test per me su macchine con prestazioni diverse...


lunedì 4 aprile 2011

Word Regex Tag Replace

Un avventura pesantella ma alla fine ne esco a testa alta.
Supponiamo di aver fatto il copia e incolla di un testo da Word e di
voler rimuovere tutto o quasi "meglio tutto" la formattazione di Word.

Per poterlo fare o si ha la piena conoscenza di tutti gli attributi
che usa word.. o si trova un sistema che vale per tutti.

Ed ecco che ancora una volta regular expression ci torna comoda !

pattern : " [a-z]*="[a-zA-Z\-0-9:;() ._,&]*"
utilizzo: curText = Regex.Replace(oldText, " [a-z]*=\"[a-zA-Z\\-0-9:;() ._,&]*\"", "", RegexOptions.Multiline);

Dove:

curText è una stringa che conterrà il nuovo valore
Regex arriva da System.Text.RegularExpressions
oldText è la stringa che contiene il testo copia-incollato da Word

Il pattern
[a-z]*="[a-zA-Z\-0-9:;() ._&]*

[a-z]*
tutte le occorrenze di tutte le lettere.
[a-zA-Z\-0-9:;() ._&]*
tutte le occorrenze di tutte le lettere maiuscole/minuscole e i caratteri -:;() ._&


Trovare questo pattern non è stato semplice, e garantisco che funziona
per Word 2010.

Buon divertimento...

venerdì 1 aprile 2011

keyPressEvent javascript

Supponiamo di avere la necessità di simulare la pressione di un bottone o fronte della pressione del carattere invio su un altro controllo..

Ecco l'esmpietto facile facile.

<html>
<head>
<script type="text/javascript">
function keyCodeEnterPress (event){
if (event.keyCode==13) { document.getElementById('btnDemo').click();
}
</script>
</head>
<body>
<input size="40" value="coraggio, premi invio!" onkeypress="keyCodeEnterPress (event);">
<input type ="button" id="btnDemo" value="test" onclick="alert('Fatto')" >
</body>
</html>