C# 3.0 introduce una interessante feature denominata extension method (vedi C# 3.0 Specification per maggiori dettagli) che in sostanza permette di "agganciare" metodi a qualunque tipo senza dover creare una classe derivata. Il tutto senza penalizzazioni in termini di performance visto che il lavoro è svolto a tempo di compilazione.
Supponiamo ad es. di voler mettere a disposizione di ogni oggetto un metodo Serialize che effettua la serializzazione dello stesso utilizzando System.Xml.Serialization.XmlSerializer. Potremmo scrivere un extension method del tipo:
using
System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
namespace
System.Xml.Serialization
{
public static class SerializationExtensions
{
public static void Serialize(this object obj, TextWriter writer)
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(writer, obj);
}
}
}
// ...
public
class Person
{
public string FirstName, LastName;
}
Person p = new Person { FirstName = "Mario", LastName = "Rossi" };
p.Serialize(Console.Out);
Per poter disporre del metodo Serialize per ogni oggetto è sufficiente importare il namespace System.Xml.Serialization!
Ovviamente gli extension method funzionano con qualunque tipo, quindi: delegate, System.ValueType, ...
Facciamo un altro esempio: supponiamo di voler fare in modo che per ogni oggetto sia possibile agganciare, a tempo di esecuzione, delle "dynamic property" e quindi poter scrivere una cosa del tipo:
object o1 = new object();
o1.SetProperty("Name", "Mario Rossi");
Console.WriteLine(o1.GetProperty("Name", ""));
Per fare questo è sufficiente scrivere una classe con un po' di extension method:
public
static class DynamicObjectExtensions
{
private static Dictionary<object, Dictionary<string, object>> properties = new Dictionary<object, Dictionary<string, object>>();
public static void SetProperty(this object obj, string name, object value)
{
Dictionary<string, object> tmp;
if (!properties.TryGetValue(obj, out tmp))
{
tmp = new Dictionary<string, object>();
properties[obj] = tmp;
}
tmp[name] = value;
}
public static T GetProperty<T>(this object obj, string name, T defaultValue)
{
Dictionary<string, object> tmp;
object value;
if (properties.TryGetValue(obj, out tmp))
{
if (tmp.TryGetValue(name, out value))
return (T)Convert.ChangeType(value, typeof(T));
else
return defaultValue;
}
else
return defaultValue;
}
}
Sulla stessa falsa riga sarebbe possibile aggiungere i metodhi HasProperty, RemoveProperty, ...