У більшості випадків код відображення даних із сховища у домені об'єкти виходить одноманітним та самоповторним.
Даний шаблон пропонує описати правила відображення, які будуть загальними для всіх об'єктів.
При використанні генерації коду, розробник пише програму, яка приймає метадані та створює класи відображення. Дані класи нічим не відрізняються від написаних вручну.
З іншого боку рефлексія знаходить описані поля і співвідносить їх із колонками таблиці.
Нехай дана таблиця у сховищі.
public class PlayerTable
{
public ind id { get; set; }
public string name { get; set; }
}
Та об'єкт який описую цю таблицю.
public class Player
{
public int Id { get; set; }
public string Name { get; set; }
}
Тоді опишемо загальний код відображення.
class DataMap
{
private class ColumnMap
{
public string FieldName { get; set; }
public string ColumnName { get; set; }
}
private Type _domainClass;
private string _tableName;
private ICollection<ColumnMap> _columnMetedatas = new List<ColumnMap>();
public DataMap(Type domainClass, string tableName)
{
_domainClass = domainClass;
_tableName = tableName;
}
public void AddMetadata(string fieldName, string columnName)
{
_columnMetedatas.Add(new ColumnMap
{
FieldName = fieldName,
ColumnName = columnName,
});
}
public string GetTableName()
{
return _tableName;
}
public IEnumerable<string> GetColumns()
{
return columnMetedatas.Select(c => c.ColumnName);
}
public object GetDomainObject(object record)
{
// використання рефлексії
var domainObject = Activator.CreateInstance(_domainClass);
foreach(var metadate in _columnMetedatas)
{
var tableColumnData = record.Read(metadate.ColumnName);
var propertyInfo = _domainClass.GetProperty(metadate.FieldName);
propertyInfo.SetValue(domainObject, tableColumnData);
}
return domainObject;
}
}
class PlayerMapper
{
private DataMap _dataMap;
public PlayerMapper()
{
_dataMap = new DataMap(typeof(Player), "PlayerTable");
_dataMap.AddMetadata("Id", "id");
_dataMap.AddMetadata("Name", "name");
}
public Player findObject (int id) {
var sql = $@"
SELECT {string.Join(" , ", _dataMap.GetColumns())}
FROM {_dataMap.GetTableName()}
WHERE id = {id}";
var record = db.Execute(sql);
return _dataMap.GetDomainObject(record) as Player;
}
. . .
}