我想就如何解决以下问题提出建议。
首先,我有这些可变的类。重要的类是ImageData,它包含一个图像作为字节数组。
public class RootData
{
public string Name { get; set; }
public string Description { get; set; }
public ImageData Image { get; set; }
public List<ChildData> Children { get; set; }
}
public class ChildData
{
public string Name { get; set; }
public ImageData Image { get; set; }
}
public class ImageData
{
public string Extension { get; set; }
public byte[] Data { get; set; }
}
类的第二个设置是这些,它们是不可变的。重要的类是ImageInfo,它包含磁盘上图像的文件路径。
public class RootInfo
{
private RootInfo()
{
}
public string Name
{
get { return this.name; }
}
public string Description
{
get { return this.description; }
}
public ImageInfo Image
{
get { return this.image; }
}
public IEnumerable<ChildInfo> Children
{
get { return this.children; }
}
public static RootInfo ToInfo(RootData rootData)
{
}
private readonly string name;
private readonly string description;
private readonly ImageInfo image;
private IEnumerable<ChildInfo> children;
}
public class ChildInfo
{
public string Name
{
get { return this.name; }
}
public ImageInfo Image
{
get { return this.image; }
}
private readonly string name;
private readonly ImageInfo image;
}
public class ImageInfo
{
public string Path
{
get { return this.path; }
}
private readonly string path;
}
现在问题,我想将RootData对象转换为RootInfo对象。我首先考虑在RootInfo类上创建一个静态方法(ToInfo),该方法接受一个RootData对象,该对象创建一个RootInfo对象。但我不想让ImageInfo类负责将图像保存在磁盘上。
您对如何以干净的方式解决这个问题有什么建议吗?
注意:这只是一个例子,真正的类更复杂但原理是相同的。
答案 0 :(得分:0)
好像你有两组相同的抽象实现。那么如何定义共享接口(IRootInfo,IChildInfo和IImageInfo)并使每个* Data和* Info类实现相应的接口?无论何时您需要使用根名称,您都可以通过界面获取它,例如:
public string GetNameOfRoot(IRootInfo root)
{
return root.Name;
}
但是不要忘记在引用中使用接口而不是concret类型:
public List<IChildInfo> Children { get; set; }
答案 1 :(得分:0)
更好地考虑接口而不是类。类可以实现一个或多个接口,并且接口可以彼此继承。让我们从只读界面开始:
public interface IReadOnlyRootInfo
{
string Name { get; }
string Description { get; }
ImageData Image { get; }
List<ChildData> Children { get; }
}
接下来,让我们添加一个可写版本:
public interface IWritableRootInfo : IReadOnlyRootInfo
{
new string Name { get; set; }
new string Description { get; set; }
new ImageData Image { get; set; }
List<ChildData> Children { get; set; }
}
现在你的具体类实现了IWritableRootInfo
,因此IReadOnlyRootInfo
:
public class RootData : IWritableRootInfo, IReadOnlyRootInfo
{
public string Name { get; set; }
public string Description { get; set; }
public ImageData Image { get; set; }
public List<ChildData> Children { get; set; }
}
现在只需将实际为RootData
的对象作为IWritableRootInfo
或IReadOnlyRootInfo
传递给其他方法。
当然,你应该继续使用ImageData
,'ChildData等。
答案 2 :(得分:0)
正确的是,ImageData
这样的信息承载类在将其转换为ImageInfo
时不应自动将其自身保存到磁盘。该操作涉及许多细节,这些细节超出了其作业基本上代表数据的任何类的范围。
这样的类提供将其转换为其他形式的方法是完全合理的,即使它们需要某种通用支持。要从数据类中获取磁盘存储的详细信息,我会做这样的事情......
所有Data类都可以获取可以将它们保存到给定(抽象)存储位置的方法。您可以创建一个接口来定义存储位置必须提供的服务:
interface IMyStorage
{
ImageInfo SaveImage(ImageData);
}
class RootData
{
...
RootInfo SaveTo(IMyStorage storage);
}
...
class ImageData
{
...
ImageInfo SaveTo(IMyStorage storage)
{
return storage.SaveImage(this);
}
}
然后你可以制作一个特定于磁盘的IMyStorage实现,它可以保存到磁盘,并封装了它的所有细节。