, , T4 (T4 VS2010, ).
T4 - , "" . , ASP/PHP . XML/XSLT.
T4 . .
, , , ( T4), , , .
, , T4:
( Visual Studio, " ", , .cs .tt, .tt . .cs)
<#
var classDefs = new []
{
new ClassDefinition
{
Name = "A",
Properties = new []
{
P ("int" , "Id" ),
P ("string" , "Name" ),
P ("B" , "FirstB" , listenToChanges:true ),
P ("B" , "SecondB" , listenToChanges:true ),
P ("B" , "ThirdB" , listenToChanges:true ),
},
},
new ClassDefinition
{
Name = "B",
Properties = new []
{
P ("int" , "Id" ),
P ("string" , "Name" ),
},
},
};
#>
namespace SO
{
using System;
using System.ComponentModel;
<#
foreach (var classDef in classDefs)
{
#>
public partial class <#=classDef.Name#> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged (string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler (this, new PropertyChangedEventArgs (name));
}
}
<#
foreach (var propertyDef in classDef.Properties)
{
#>
public <#=propertyDef.Type#> <#=propertyDef.Name#>
{
get { return <#=propertyDef.FieldName#>; }
set
{
if (<#=propertyDef.FieldName#> == value)
{
return;
}
<#
if (propertyDef.ListenToChanges)
{
#>
if (<#=propertyDef.FieldName#> != null)
{
<#=propertyDef.FieldName#>.PropertyChanged -= <#=propertyDef.ListenerName#>;
}
<#=propertyDef.FieldName#> = value;
if (<#=propertyDef.FieldName#> != null)
{
<#=propertyDef.FieldName#>.PropertyChanged += <#=propertyDef.ListenerName#>;
}
<#
}
else
{
#>
<#=propertyDef.FieldName#> = value;
<#
}
#>
<#=propertyDef.EventName#> ();
OnPropertyChanged("<#=propertyDef.Name#>");
}
}
<#=propertyDef.Type#> <#=propertyDef.FieldName#>;
partial void <#=propertyDef.EventName#> ();
<#
if (propertyDef.ListenToChanges)
{
#>
void <#=propertyDef.ListenerName#> (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (
"Instance of <#=classDef.Name#> detected a change of <#=propertyDef.Name#>.{0}",
e.PropertyName
);
<#=propertyDef.EventName#> ();
}
<#
}
}
#>
}
<#
}
#>
}
<#+
class ClassDefinition
{
public string Name;
public PropertyDefinition[] Properties;
}
class PropertyDefinition
{
public string Type;
public string Name;
public bool ListenToChanges;
public string FieldName
{
get
{
return "_" + Name;
}
}
public string ListenerName
{
get
{
return Name + "_Listener";
}
}
public string EventName
{
get
{
return "Change_" + Name;
}
}
}
PropertyDefinition P (string type, string name, bool listenToChanges = false)
{
return new PropertyDefinition
{
Type = type ?? "<NO_TYPE>",
Name = name ?? "<NO_NAME>",
ListenToChanges = listenToChanges,
};
}
#>
, :
namespace SO
{
using System;
using System.ComponentModel;
public partial class A : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged (string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler (this, new PropertyChangedEventArgs (name));
}
}
public int Id
{
get { return _Id; }
set
{
if (_Id == value)
{
return;
}
_Id = value;
Change_Id ();
OnPropertyChanged("Id");
}
}
int _Id;
partial void Change_Id ();
public string Name
{
get { return _Name; }
set
{
if (_Name == value)
{
return;
}
_Name = value;
Change_Name ();
OnPropertyChanged("Name");
}
}
string _Name;
partial void Change_Name ();
public B FirstB
{
get { return _FirstB; }
set
{
if (_FirstB == value)
{
return;
}
if (_FirstB != null)
{
_FirstB.PropertyChanged -= FirstB_Listener;
}
_FirstB = value;
if (_FirstB != null)
{
_FirstB.PropertyChanged += FirstB_Listener;
}
Change_FirstB ();
OnPropertyChanged("FirstB");
}
}
B _FirstB;
partial void Change_FirstB ();
void FirstB_Listener (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (
"Instance of A detected a change of FirstB.{0}",
e.PropertyName
);
Change_FirstB ();
}
public B SecondB
{
get { return _SecondB; }
set
{
if (_SecondB == value)
{
return;
}
if (_SecondB != null)
{
_SecondB.PropertyChanged -= SecondB_Listener;
}
_SecondB = value;
if (_SecondB != null)
{
_SecondB.PropertyChanged += SecondB_Listener;
}
Change_SecondB ();
OnPropertyChanged("SecondB");
}
}
B _SecondB;
partial void Change_SecondB ();
void SecondB_Listener (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (
"Instance of A detected a change of SecondB.{0}",
e.PropertyName
);
Change_SecondB ();
}
public B ThirdB
{
get { return _ThirdB; }
set
{
if (_ThirdB == value)
{
return;
}
if (_ThirdB != null)
{
_ThirdB.PropertyChanged -= ThirdB_Listener;
}
_ThirdB = value;
if (_ThirdB != null)
{
_ThirdB.PropertyChanged += ThirdB_Listener;
}
Change_ThirdB ();
OnPropertyChanged("ThirdB");
}
}
B _ThirdB;
partial void Change_ThirdB ();
void ThirdB_Listener (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (
"Instance of A detected a change of ThirdB.{0}",
e.PropertyName
);
Change_ThirdB ();
}
}
public partial class B : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged (string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler (this, new PropertyChangedEventArgs (name));
}
}
public int Id
{
get { return _Id; }
set
{
if (_Id == value)
{
return;
}
_Id = value;
Change_Id ();
OnPropertyChanged("Id");
}
}
int _Id;
partial void Change_Id ();
public string Name
{
get { return _Name; }
set
{
if (_Name == value)
{
return;
}
_Name = value;
Change_Name ();
OnPropertyChanged("Name");
}
}
string _Name;
partial void Change_Name ();
}
}