I have a Table class that inherits a property from its base class DbTableBase, and hides the base class property MegaList<DbColumnBase> Columns
with a more specific property MegaList<TableColumn> Columns
.
Originally my app targeted Oracle only, but a recent refactoring into a common base so I could add SQLServer and other targets caused the Velocity templates to fail. My NVelocity template module is failing on any collections that have base implementations that are hidden by a derivation because it evaluates the base property.
context.Put("table", table); // table is Table, not TableBase
...
#foreach ($c in $table.Columns)
$c.Name
#end
My container declaration is:
public class MegaList<T> : ObservableCollection<T>
{
public MegaList() {}
// etc. etc.
}
My Table type is has a _columns field that when exposed as a MegaList, NVelocity fails to iterate the leaf Table.Columns list:
public class Table : TableBase {
MegaList<ColumnBase> _columns = new MegaList<ColumnBase>();
public MegaList<ColumnBase> Columns // template takes this one, even though it is hidden
{
get { return _columns; }
}
}
public class Table : TableBase {
new public MegaList<TableColumn> Columns // Velocity ignores this, chooses base Columns
{
get { return _columns.DownCast<TableColumn>(); }
set { _columns = value.UpCast<DbTableColumn, TableColumn>(); }
}
public MegaList<TableColumn> Columns2 // Velocity sees this
{
get { return _columns; }
}
}
NVelocity is evaluating the base TableBase.Columns, yet if my template references $table.Columns2, NVelocity evaluates Table.Columns2.
I can't make the property virtual because the type is different, albeit a more specific Thinking out loud, I assume this behaviour is because VelocityContext holds "object" references, and has some sort of problem with choosing the correct property in the case of multiples, though I would assume it should choose the leaf property.