Web Log di Adrian Florea

"You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
posts - 440, comments - 2715, trackbacks - 3944

My Links

Archives

Post Categories

Image Galleries

.RO Blogs

.RO People

.RO Sites

Blogs

Furls

Links

vinCitori

giugno 2004 Blog Posts

Unable to start debugging on the web server - allora cambiate ASP.NET version

Pensavo che tutti avessero già scoperto la soluzione, ma dopo aver visto che Paschal Leloup (non sono tanti i blogger .NET con quasi 1500 post...) ha dovuto cancellare completamente il .NET 2.0 appena installato, mi sono detto che forse vale la pena di postarla :-) Quindi, è molto semplice: se dopo aver installato .NET 2.0 Beta 1, non vi va più niente nei "vecchi" progetti .NET 1.1 e ottenete: "Error while trying to run project: Unable to start debugging on the web server.Click Help for more information." allora andate subito in Internet Services Manager, click destro su Properties per il vostro local web site,...

posted @ mercoledì 30 giugno 2004 18:16 | Feedback (74) | Filed Under [ Carillon .NET ]

Più singleton e meno cose strane :-)

Nel mio articolo "L'individuazione via reflection delle classi singleton all'interno del Framework .NET" - grazie per il rating 4,70 :-) - trovavo le seguenti 3 classi singleton: Microsoft.JScript.Empty Microsoft.JScript.Missing System.DBNull e finivo l'articolo con una mia perplessità: "Giocando con vari test e cambiando leggermente i requisiti di implementazione ho scoperto che la classe System.Reflection.Missing ha il costruttore internal anziché private, per il resto è un singleton puro. Mi chiedo se si tratta di una disattenzione da parte degli sviluppatori del Framework oppure se è stata pensata come singleton solo all'esterno del Framework. Un caso simile è quello della classe interna System.Empty dove di...

posted @ mercoledì 30 giugno 2004 02:13 | Feedback (18) | Filed Under [ Pattern Dappertutto Un po' di numeri ]

Void & System.Void - finalmente, errore :-)

Un po' di giorni fa segnalavo il fatto strano che questo codice: class Foo{  static void Main()  {    System.Console.WriteLine(System.Void.Equals(null, null));    System.Console.Read();  }} compilava (con Visual C# .NET Compiler version 7.10.3052.4) senza errori. Stasera ho scaricato e installato il ".NET Framework Version 2.0 Redistributable Package Beta 1 (x86)" uscito oggi e compilando (con Visual C# .NET Compiler version 8.00.40607.16) lo stesso codice di sopra ho ottenuto, finalmente, l'errore che aspettavo: error CS0673: System.Void cannot be used from C# -- use typeof(void) to get the void type object. Adesso sono più contento :-)

posted @ mercoledì 30 giugno 2004 00:49 | Feedback (29) | Filed Under [ Carillon .NET Bugs? ]

Sì, le interfacce derivano da System.Object :-)

Adesso è più chiaro. Questo codice: using System;interface IFoo{}class Foo{  static void Main()  {    Type i = typeof(IFoo);    Type o = typeof(object);    Console.WriteLine("{0} {1} da {2}", i.Name, i.IsSubclassOf(o) ? "deriva" : "non deriva", o.Name);    Console.Read();  }} scrive "IFoo deriva da Object" a console. Si può dire che le interfacce derivano in tutti gli effetti da System.Object. Per chi non è ancora convinto, provi a vedere che il seguente codice compila: using System;interface IFoo{}class Foo{  static void Main()  {    Console.WriteLine(IFoo.Equals(null, null));    Console.Read();  }} e scrive True a console.

posted @ lunedì 28 giugno 2004 17:18 | Feedback (22) | Filed Under [ Carillon .NET ]

Proprietà read-only e setter

La proprietà Length di System.IO.Stream e di tutte le sue classi derivate non è l'unica proprietà read-only per cui esiste nella stessa classe un metodo setter ma lo sono anche le proprietà In, Out ed Error della classe System.Console: public sealed class Console{  //...  private static TextReader _in;  public static TextReader In  {    get    {      //...    }  }  public static void SetIn(TextReader newIn)  {    //...  }  private static TextReader _out;  public static TextReader Out  {    get    {      //...    }  }  public static void SetOut(TextWriter newOut)  {    //...  }  private static TextWriter _error;  public static TextReader Error  {    get    {      //...    }  }  public static void SetError(TextWriter newError)  {    //...  }  //...} Ho verificato via reflection che questi sono gli unici casi all'interno del Framework di proprietà read-only pubbliche con setter pubblico nella stessa classe pubblica. Secondo me è interessante questa...

posted @ lunedì 28 giugno 2004 11:32 | Feedback (14) | Filed Under [ Carillon .NET Pattern Dappertutto ]

System.IO.Stream.Length

public abstract class Stream: MarshalByRefObject, IDisposable{  //...  public abstract long Length {get;}  public abstract void SetLength(long value);  //...} Proprietà read-only e setter come metodo...Secondo voi è stata una scelta oppure uno strano errore progettuale? Lo so, prima o poi scriverò una mail a Brad... :-)

posted @ lunedì 28 giugno 2004 01:13 | Feedback (8) | Filed Under [ Carillon .NET Pattern Dappertutto ]

BCL: 30% sealed

"In general I am not a big fan of sealing classes arbitrarly. As a general rule we designed classes in the BCL with extensibility in mind. However, from a pragmatic standpoint that is not always possible. [...] a fully extensible design is not always practical [...]" (Brad Abrams, SLAR, p. 424) Incuriosito da quanto vuol dire in numeri la frase di Brad "I am not a big fan of sealing" mi sono messo a contare (no, non a mano!) tutte le classi sealed tra le classi non abstract in tutti i namespace sotto System, System ovviamente compreso. Il risultato? 1695 classi...

posted @ lunedì 28 giugno 2004 00:22 | Feedback (7) | Filed Under [ Pattern Dappertutto Un po' di numeri ]

System.Object come tipo base di un tipo interfaccia?

Alla pagina 129 (p. 145 del file PDF) dello "Standard ECMA-334, C# Language Specification, 2nd edition", ho incontrato una frase curiosa: "If T is an interface-type, the base types of T are the base interfaces of T and the class type object" (le sottolineature in tutte le citazioni sono mie) Un tipo interfaccia ha come tipo base anche System.Object? In che modo dobbiamo interpretare questa affermazione? Solo il fatto che "le interfacce sono sempre considerate come tipi di riferimento"? (Richter, p. 330) Come possiamo verificare via reflection il fatto che un'interfaccia ha come tipo base la System.Object? Sempre Richter dice, alla pagina...

posted @ domenica 27 giugno 2004 16:17 | Feedback (8) | Filed Under [ Carillon .NET ]

MS? Multilanguage Standard! :-)

Chi si immagina che MS in MSCorLib.dll sia l'acronimo per Microsoft, si sbaglia :-) MS in questo caso vuol dire Multilanguage Standard! Parola di Jeffrey Richter

posted @ sabato 26 giugno 2004 16:36 | Feedback (13) | Filed Under [ Un po' di storia Varie ]

E' morto il più vecchio programmatore vivente...

E' morto Bob Bemer che nella sua vita ha avuto tanti bravi figli... Alcuni di questi: il codice ASCII le sequenze di escape gli 8-bit per byte il nome COBOL il concetto di registry il backslash il primo sistema computerizzato di animazione 3DNel '59 proponeva il word processing mentre nel '71 lanciava un segnale d'allarme sul problema Y2K... Alla domanda "How did you arrive at the name COBOL?" ecco la sua risposta: "Cobol to me has a nice round sound - a lyrical quality (drawing an imaginary hourglass in the air). The sound reminds me of a women’s figure."

posted @ sabato 26 giugno 2004 03:44 | Feedback (11) | Filed Under [ Un po' di storia ]

Michael Collins è nato a Roma!

Raccontavo ad Andrea, in macchina, mentre andavamo al ristorante per la cena dopo il bellissimo workshop, quanto innamorato sono dell'Italia, quanto credo nell'Italia e negli italiani, come non ci sia più strada di ritorno per questo amore. Questi giorni ho preso una piccola vacanza e tengo le orecchie un po' lontane dal canto delle sirene .NET e così ho scoperto una cosa forse poco conosciuta dagli italiani: che tra tutti gli uomini andati sulla Luna, l'unico NON-nato negli Stati Uniti è nato a Roma! Michael Collins, Apollo 11 Command Module Pilot

posted @ venerdì 25 giugno 2004 16:45 | Feedback (10) | Filed Under [ Un po' di storia Varie ]

A domani

Gli workshop sono un'opportunità di conoscere non solo cose nuove ma anche persone nuove. A parte questa considerazione demente che comunque sappiamo tutti :-) per riconoscerci domani (se vi va) qui trovate un piccolo aiuto.

posted @ lunedì 21 giugno 2004 12:03 | Feedback (6) | Filed Under [ Varie ]

Void & System.Void

Possono anche sembrarvi uguali i seguenti due snippet: // Snippet 1using System;class Foo{  static void Main()  {    Console.WriteLine(Void.Equals(null, null));    Console.Read();  }} // Snippet 2class Foo{  static void Main()  {    System.Console.WriteLine(System.Void.Equals(null, null));    System.Console.Read();  }} ma non lo sono per niente! :-) Mentre il primo dà l'errore che tutti si aspettano: System.Void cannot be used from C# -- use typeof(void) to get the void type object. il secondo scrive senza problemi un bel True a console! :-) Dovrei pensare un po' al perché...

posted @ lunedì 21 giugno 2004 00:30 | Feedback (13) | Filed Under [ Carillon .NET Bugs? ]

Quiz Sharp 28

using System;struct Foo{  public double Value;  public Foo(double d)  {    Value = Double(d);  }  private double Double(double d)  {    return 2 * d;  }}class Test{  static void Main()  {    Foo f = new Foo(1);    Console.WriteLine(f.Value);    Console.Read();  }} Quale tra le seguenti parole chiave si deve aggiungere al codice qui sopra per renderlo compilabile senza errori: A. static (per avere: private static double Double(double d)) B. new (per avere: Value = new Double(d);) C. this (per avere: Value = this.Double(d);)

posted @ domenica 20 giugno 2004 17:04 | Feedback (10) | Filed Under [ Quiz Sharp ]

Abuso dell'ereditarietà

A parte il fatto che ha risposto correttamente all'ultimo quiz :-) Gianluca, attento come sempre,  mi ha fatto notare nel libro di Box & Sells un esempio in qualche modo simile al mio, ma molto più incasinato. Lo trovate nell'edizione italiana alla pagina 171, listato 6.6 "Abuso dell'ereditarietà".

posted @ lunedì 14 giugno 2004 16:41 | Feedback (8) | Filed Under [ Quiz Sharp ]

Quiz Sharp 27

using System;class Foo1{  public override string ToString()  {    return "Foo1";  }}class Foo2: Foo1{  private new string ToString()  {    return "Foo2";  }}class Foo3: Foo2{  public override string ToString()  {    return base.ToString();  }}class Foo{  static void Main()  {    Console.WriteLine(new Foo3().ToString());    Console.Read();  }} Cosa viene visualizzato a console? A. Foo1 B. Foo2 C. Questo è il mio 100° post! :-) D. non compila ('Foo2.ToString()' is inaccessible due to its protection level)

posted @ lunedì 14 giugno 2004 12:14 | Feedback (8) | Filed Under [ Quiz Sharp ]

The null type (un po' più chiaro)

In riferimento alla mia perplessità sul null type, ho trovato alcuni spunti in questo documento: C++/CLI Language Specification. Candidate Base Document: p. 43"The null type is a special type that exists solely to support the null literal, nullptr (also referred to as the null value constant). No instances of this type can be created; the only way to obtain a value of this type is via the nullptr literal, whose type is the null type." p. 37"The null literal (nullptr) is not an lvalue." p. 61"The sizeof operator shall not be applied to an expression that has null type." L'equivalente di nullptr in C#...

posted @ lunedì 14 giugno 2004 02:23 | Feedback (11) | Filed Under [ Carillon .NET ]

String ==-ity in Java e C# (cosa dicono gli standard)

In riferimento al mio post precedente, vediamo cosa dicono gli standard: Java Language Specification, 2nd edition Standard ECMA-334. C# Language Specification, 2nd edition 15.21.3While == may be used to compare references of type String, such an equality test determines whether or not the two operands refer to the same String object. The result is false if the operands are distinct String objects, even if they contain the same sequence of characters. The contents of two strings s and t can be tested for equality by the method invocation s.equals(t).3.10.5Strings computed at run time are newly created and therefore distinct. 14.9.7 (p. 167)Two...

posted @ domenica 13 giugno 2004 19:28 | Feedback (11) | Filed Under [ Carillon .NET ]

0 non è maggiore di -0

Se vi chiedete perché 0 > -0 è False, la risposta è semplicissima: 0 == -0E se vi chiedete ancora perché 0 == -0, la risposta è nuovamente semplicissima :-)Il risultato dell'operatore: int operator -(int x); si ottiene sottraendo x da 0. Nel nostro caso: -0 = 0 - 0 = 0 quindi 0 == -0

posted @ domenica 13 giugno 2004 16:12 | Feedback (9) | Filed Under [ Carillon .NET ]

La bisnonna di Java :-)

In questo post di una tenerezza forte, del papà di Java, potete leggere la storia della sua nonna (l'estate scorsa ha festeggiato il 98° compleanno!) e ammirare la foto di niente altri che la bisnonna di Java :-) la signora Margaret Carolyn (Svensdötter) Morrison.

posted @ sabato 12 giugno 2004 18:11 | Feedback (10) | Filed Under [ Un po' di storia Foto Quiz ]

String ==-ity in Java e C#

L'articolo "(Not So) Stupid Questions: String Equality" su java.net, è nato dalle perplessità di Vladimir V. Ostromensky inviate alla redazione del sito, riguardanti il risultato "strano" del seguente codice Java: Compile the following: // StringTester.javapublic class StringTester{  public static void main(String args[])   {    String aString = "myValue";    String bString = "myValue";    String cString = "";    if(args.length ==1 ) cString = args[0];    boolean test1 = aString.equals(bString);    System.out.println("a.equals(b): " + aString + ".equals("+bString+") is " + test1);    boolean test2 = aString == bString;    System.out.println("a==b: " + aString + " == " + bString+" is " + test2);    boolean test3 = aString.equals(cString);    System.out.println("a.equals(c): " + aString + ".equals("+cString+") is " + test3);    boolean test4 = aString...

posted @ sabato 12 giugno 2004 17:26 | Feedback (7) | Filed Under [ Carillon .NET ]

Array Initializer :-)

Via Alex Papadimoulis, un modo più "simpatico" per inizializzare un array di n + 1 stringhe a string.Empty: int n = 99;string[] arr = string.Empty.PadRight(n, ',').Split(','); Ho modificato un po' il codice, il post originale si trova qui.

posted @ sabato 12 giugno 2004 01:24 | Feedback (2) | Filed Under [ Carillon .NET Varie ]

Quiz Sharp 26 (Steven John Metsker)

Ispirato da un esempio di Steven John Metsker ("Design Patterns in C#", p. 158, 382) class FooBase{  string _name;  FooBase(string name)  {    _name = name;  }}class Foo: FooBase{} Vi aspettate: A. compila senza warning o errori B. compila con warning C. non compila (errore di compilazione)

posted @ venerdì 11 giugno 2004 01:12 | Feedback (7) | Filed Under [ Quiz Sharp ]

The null type?

Una frase un po' misteriosa alla pagina 61 in basso nello standard ECMA-334 (C# Language Specification): The type of a null-literal is the null type. Voi cosa ci capite? Cosa vuol dire "the null type"?

posted @ giovedì 10 giugno 2004 17:55 | Feedback (6) | Filed Under [ Carillon .NET ]

Quiz Sharp 25

class Foo{  const object refTypeConst = null;  const System.DateTime valTypeConst = System.DateTime.MinValue;} Vi aspettate: A. compila senza errori B. errore di compilazione sulla dichiarazione della refTypeConst C. errore di compilazione sulla dichiarazione della valTypeConst

posted @ giovedì 10 giugno 2004 15:11 | Feedback (5) | Filed Under [ Quiz Sharp ]

Quiz Sharp 24

using System;class Bar{  static int i = 0;  class Foo  {    public Foo()    {      i++;    }    static Foo()    {      i--;    }  }  static void Main()  {    Foo f1 = new Foo();    Foo f2 = new Foo();    Console.WriteLine(i);    Console.Read();  }} Cosa viene visualizzato a console? A. 0 B. 1 C. 2

posted @ giovedì 10 giugno 2004 01:10 | Feedback (8) | Filed Under [ Quiz Sharp ]

Quiz Sharp 23 (Clive Tooth)

Un quiz simpatico, di Clive Tooth: Would this class declaration compile? class Class{  delegate Delegate Delegate(Delegate Delegate);  static Delegate Static(Delegate Static)  {    return Static;  }}

posted @ mercoledì 9 giugno 2004 03:36 | Feedback (8) | Filed Under [ Quiz Sharp ]

Quiz Sharp 22

class Foo{  int P  {    get    {      return 1;    }  }  string get_P()  {    return "1";  }} Vi aspettate: A. errore sulla proprietà B. errore sul metodo C. compila senza errori

posted @ mercoledì 9 giugno 2004 01:19 | Feedback (7) | Filed Under [ Quiz Sharp ]

Quiz Sharp 21

using System;class Foo{  static void Main()  {    string s;    int i = 1;    s = i == 1 ? "A" : s + "B";    Console.WriteLine(s);    Console.Read();  }} Cosa viene visualizzato a console? A. A B. compila con warning C. non compila

posted @ lunedì 7 giugno 2004 12:12 | Feedback (6) | Filed Under [ Quiz Sharp ]

Quiz Sharp 20

using System;class Foo{  static Foo()  {    Console.WriteLine(i);  }  static int i = 1;  static void Main()  {    Console.Read();  }} Cosa viene visualizzato a console? A. 0 B. 1 C. non viene visualizzato nulla.

posted @ domenica 6 giugno 2004 17:06 | Feedback (7) | Filed Under [ Quiz Sharp ]

Quiz Sharp 19

using System;struct A{}struct B{  public A A;}struct C{  public A A;  public int I;}class Foo{  static unsafe void Main()  {    Console.WriteLine("A:{0} B:{1} C:{2}", sizeof(A), sizeof(B), sizeof(C));    Console.Read();  }} Si compila con "Allow Unsafe Code Blocks = True" se utilizzate VS, oppure "/unsafe" da linea di comando (csc) Cosa viene visualizzato a console? A. 1 1 8 B. 1 2 5 C. 0 0 4

posted @ sabato 5 giugno 2004 13:50 | Feedback (6) | Filed Under [ Quiz Sharp ]

Patty Quiz 1

Visti i feedback abbastanza buoni :-) della serie di quiz su C#, ho pensato ad aprirne un'altra, forse più difficile, su design patterns. L'ho chiamata Patty Quiz per toglierle un po' di occhiaie e non per ultimo, perché mi piace tanto Patty Pravo :-) Il codice qui sotto vuole calcolare il numero delle foglie (nodi senza figli) del grafo orientato determinato dal nodo di partenza root: using System;using System.Collections;interface Component{  void Add(Component c);  int Count{get;}}class Composite: Component{  private ArrayList _children = new ArrayList();  public void Add(Component c)  {    _children.Add(c);  }  public int Count  {    get    {      int count = 0;      foreach(Component c in _children)      {        count += c.Count;      }      return count;    }  }}class Leaf: Component{  public void Add(Component c)  {    throw new NotSupportedException("Le foglie non hanno...

posted @ venerdì 4 giugno 2004 00:58 | Feedback (11) | Filed Under [ Quiz Sharp Pattern Dappertutto ]

Quiz Sharp 18 ("piccola" variazione sul Quiz Sharp 17)

Cambiate nel Quiz Sharp 17 il tipo Weird da struct a class. Cosa viene visualizzato adesso a console? A.21 B.22 C.24 Già sento un "mumble" di qualcuno :-)

posted @ giovedì 3 giugno 2004 17:00 | Feedback (5) | Filed Under [ Quiz Sharp ]

Quiz Sharp 17 (ispirato da un post di Cyrus Najmabadi)

Questo quiz è ispirato da un bellissimo post di Cyrus Najmabadi (C# IDE Team) - che solo a maggio ha postato nel suo blog per 73 volte! :-) using System;class C1{  public static void M(Weird w)  {    w.ToString();    Console.WriteLine(w.ToString());  }}class C2{  public static void M(Weird w)  {    NewMethod(w);    Console.WriteLine(w.ToString());  }  private static void NewMethod(Weird w)  {    w.ToString();  }}struct Weird{  private int _i;  public Weird(int i)  {    _i = i;  }  public override string ToString()  {    _i++;    return _i.ToString();  }}class Foo{  static void Main()  {    Weird w = new Weird(0);    C1.M(w);    C2.M(w);    Console.Read();  }} Cosa viene visualizzato a console? A.21 B.22 C.24

posted @ giovedì 3 giugno 2004 16:43 | Feedback (5) | Filed Under [ Quiz Sharp ]

Quiz Sharp 16

Questo è un po' troppo semplice, ma lo posto lo stesso :-) using System;class Foo{  static void Main()  {    Console.WriteLine(Convert.ToBoolean(Convert.ToInt32(Convert.ToChar(Convert.ToInt32(false)))));    Console.WriteLine(Convert.ToBoolean(Convert.ToInt32(Convert.ToChar(Convert.ToInt32(false).ToString()))));    Console.Read();  }} Cosa viene visualizzato a console? A.FalseFalse B.FalseTrue C.TrueFalse Tanti dei metodi della classe System.Convert sono riservati per un utilizzo futuro.

posted @ mercoledì 2 giugno 2004 22:48 | Feedback (7) | Filed Under [ Quiz Sharp ]

Quiz Sharp 15

using System;enum Foo{  A,  B = A - 1,  C}class Bar{  static void Main()  {    Console.WriteLine(Foo.C);    Console.Read();  }} Cosa viene visualizzato a console? A. A B. 0 C. C

posted @ mercoledì 2 giugno 2004 13:12 | Feedback (6) | Filed Under [ Quiz Sharp ]

Quiz Sharp 14

using System;enum Numero{  Uno = 1,  Due,  Tre,  Quattro,  Cinque}class Foo{  static void Main()  {    Console.WriteLine((Numero)(Numero.Cinque - Numero.Tre));    Console.Read();  }} Cosa viene visualizzato a console? A. Numero.Due B. Due C. 2

posted @ martedì 1 giugno 2004 16:10 | Feedback (6) | Filed Under [ Quiz Sharp ]

Opposites are not contradictory but complementary :-)

Questo pezzo di codice, anche se è troppo scolastico, lo so..., magari permetterà ad alcuni di capire meglio perché MinValue = MaxValue + 1 e cosa vuol dire complemento binario: using System;class Foo{  static void Main()  {    Console.WriteLine("MinValue in binario {0}", Convert.ToString(int.MinValue, 2).PadLeft(32, '0'));    Console.WriteLine("MaxValue in binario {0}", Convert.ToString(int.MaxValue, 2).PadLeft(32, '0'));    Console.WriteLine("MinValue {0} il complemento binario di MaxValue", int.MinValue == ~int.MaxValue ? "è" : "non è");    Console.Read();  }}

posted @ martedì 1 giugno 2004 14:35 | Feedback (14) | Filed Under [ Carillon .NET ]

Così gli ultimi saranno i primi :-)

Responsabile per il loop infinito notato qui da M.rkino: for(int i = int.MinValue; i <= int.MaxValue; i++){  Console.Write(".");} è questa "identità": MaxValue + 1 = MinValue cioè, all'ultimo i++ il valore della i da MaxValue ridiventa MinValue.

posted @ martedì 1 giugno 2004 01:44 | Feedback (5) | Filed Under [ Quiz Sharp Carillon .NET ]

più O meno? più E meno! :-)

I campi MaxValue e MinValue forniti dal tipo System.Int32 sono due costanti, definite rispettivamente 0x7fffffff (0 seguito da 31 1) e 0x80000000 (1 seguito da 31 0), cioè l'uno è il complemento binario dell'altro. public struct Int32 //...{ public const int MaxValue = 0x7fffffff; public const int MinValue = unchecked((int)0x80000000); //...} L'operatore unchecked si deve al fatto che la costante hexadecimale 0x80000000 è del tipo uint (Pow(2, 31)) e il cast ad un int produce overflow (Pow(2, 31) > MaxValue). Questi valori spiegano l'osservazione di M.rkino che Int32.MinValue = -Int32.MinValue.Vediamo qui di seguito come:Abbiamo:MinValue = -Pow(2, 31)MaxValue = Pow(2,...

posted @ martedì 1 giugno 2004 01:08 | Feedback (8) | Filed Under [ Carillon .NET ]

Powered by:
Powered By Subtext Powered By ASP.NET