我有一個維護應用程序,必須將企業數據(從各種數據庫/表)轉換爲平面文件,每個平面文件都以特定的格式供遺留應用程序使用。我已經得到了數據模型,如設計一個數據模型來平面文件轉換...委託或繼承?
public class StatusCode
{
public String Id { get; set; }
public Char Level { get; set; }
public String Description { get; set; }
}
我將選擇從數據源中某個子集或所有的這些記錄。我需要將每個實體映射到文件的一行,這可能需要調整數據(填充,轉換或處理null
)。
public delegate String MapEntity<T>(T entity);
public MapEntity<StatusCode> MapStatusCode = delegate(StatusCode entity)
{
return String.Format("{0},{1},{2}",
entity.Id.PadLeft(3, '0'),
entity.Level == 'S' ? 0 : 1,
entity.Description ?? "-");
}
問題是,我該如何編寫轉換類?我是否提供了一個帶有映射委託的「DefaultFileCreator」?
public interface IFileCreator
{
Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities);
}
public class DefaultFileCreator : IFileCreator
{
public Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities)
{
StringBuilder sb = new StringBuilder();
foreach (T entity in entities)
sb.AppendLine(map(entity));
return Encoding.Default.GetBytes(sb.ToString());
}
}
...
fileCreator.Create(MapStatusCode, repository<StatusCode>.FindAll());
...
有了這個解決方案,我很關心我應該在哪裏以及在什麼範圍內保留映射代理。我怎麼打電話給他們不知道T
(如果我需要)。
或者,我是否更改接口並要求具體類中的映射?
public interface IFileCreator<T>
{
Byte[] Create(IEnumerable<T> entities);
}
public abstract class FileCreator : IFileCreator<T>
{
protected abstract String Map(T entity);
public Byte[] Create(IEnumerable<T> entities)
{
StringBuilder sb = new StringBuilder();
foreach (T entity in entities)
sb.AppendLine(Map(entity));
return Encoding.Default.GetBytes(sb.ToString());
}
}
public class StatusCodeFile : FileCreator<StatusCode>
{
public override String Map(T entity)
{
return String.Format("{0},{1},{2}",
entity.Id.PadLeft(3, '0'),
entity.Level == 'S' ? 0 : 1,
entity.Description ?? "-");
}
}
該解決方案在具體類中爆炸,但它們與地圖代理一樣薄。而且我更願意與IFileCreator<T>
和一家工廠合作。 (再次,只在必要時)。
我假設一些基類很有用,因爲StringBuilder
循環和Byte[]
編碼很直接。具體類應該在基類中設置委託屬性(而不是調用抽象方法)?我應該在方法上保留類型參數(以及如何影響基類/具體類)?
我想出任何解決方案。我的主要目標是便於維護。我現在有12個模型/文件,這可能會增加到21.我可能需要在任何文件中插入任意的頁眉/頁腳行(這就是爲什麼我喜歡可覆蓋的基類方法Map)。
我也在考慮重寫每個具體類MapEntity(delegate)中的抽象屬性。覆蓋方法Map(T)的效果相同。不同的外觀。 – 2009-09-04 13:33:45