我有一個類(當前稱爲FileHandler),它處理文件。 它看起來是這樣的:文件訪問設計模式
public class FileHandler : IDisposable
{
private readonly IObjectService service;
private readonly string destination;
private readonly string fileName;
private readonly string fullPath;
private Metadata metadata;
public FileHandler(IObjectService service, string destination, string fileName)
{
this.service = service;
this.destination = destination;
this.fileName = fileName;
this.fullPath = Path.Combine(destination, fileName);
}
public XDocument GetMetadata(string exifToolPath)
{
if (!File.Exists(this.fullPath))
throw new FileNotFoundException();
return new XDocument(GetFullXml(exifToolPath));
}
public string GetThumbnail()
{
this.service.Download(this.destination, this.fileName); // Get our file
if (File.Exists(this.fullPath))
{
//if (this.metadata != null)
//{
//}
return null;
//using (var fs = File.OpenRead(this.fullPath))
//{
//}
}
return "";
}
public void Dispose()
{
this.service.Dispose();
}
private XElement GetFullXml(string exifToolPath)
{
string args = string.Format("-X \"{0}\"", this.fullPath);
string output = RunProcess(exifToolPath, args);
output = Sanitize(output);
return new XElement("FullMetadata", XElement.Parse(output));
}
private string RunProcess(string exifToolPath, string args)
{
if (String.IsNullOrEmpty(exifToolPath))
throw new SystemException("EXIFTool Executable Path Not Configured");
if (!File.Exists(exifToolPath))
throw new SystemException("EXIFTool Executable Not Found: " + exifToolPath);
var process = new Process {
StartInfo = {
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
FileName = exifToolPath,
Arguments = args }
};
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return output;
}
private string Sanitize(string s)
{
return s.Replace("&", string.Empty);
}
}
現在,我和我的命名類鬥爭。最近,我開始使用服務/資源庫設計模式,所以我所有的類要麼庫或服務這使得容易對其進行命名:)
現在我想這樣做我的文件處理程序。
這是我的需要:
我從亞馬遜桶 我需要得到它的基於文件MIME I型生成縮略圖元 下載文件(圖片只是調整並保存,視頻使用ffmpeg,而其他一切都使用基於擴展名的默認縮略圖)
那麼,我的問題是什麼樣的設計模式?
我試過使用策略模式,但問題是在獲取元數據後需要創建具體類。
請幫助:)
更新1
好了,沒有人回答,所以這裏是一個位的代碼,我寫信給解決這一問題。有人可以檢查它,並確保我不是很厚?
所以,我創建了一個基礎文件這樣的:
public class File : IDisposable
{
public readonly IObjectService service;
public readonly string destination;
public readonly string fileName;
public readonly string fullPath;
private XNamespace SystemNamespace = "http://ns.exiftool.ca/File/System/1.0/";
private XNamespace FileNamespace = "http://ns.exiftool.ca/File/1.0/";
private XNamespace Composite = "http://ns.exiftool.ca/Composite/1.0/";
public XDocument Document { get; set; }
public File(IObjectService service, string destination, string fileName)
{
this.service = service;
this.destination = destination;
this.fileName = fileName;
this.fullPath = Path.Combine(destination, fileName);
}
public XDocument GenerateMetadataFromFile(string exifToolPath)
{
if (!System.IO.File.Exists(this.fullPath))
throw new FileNotFoundException();
return new XDocument(GetFullXml(exifToolPath));
}
public virtual Metadata GetMetadata(string exifToolPath)
{
this.Document = this.GenerateMetadataFromFile(exifToolPath);
var metadata = new Metadata()
{
ReferenceId = this.GenerateId(),
FileSize = (string)Document.Descendants(SystemNamespace + "FileSize").FirstOrDefault(),
FileType = (string)Document.Descendants(FileNamespace + "FileType").FirstOrDefault(),
MIMEType = (string)Document.Descendants(FileNamespace + "MIMEType").FirstOrDefault(),
};
return metadata;
}
public virtual string GetThumbnail()
{
var iconPath = Resources.Resources.DocumentIconPath;
var iconName = GetDocumentIcon(System.IO.Path.GetExtension(this.fileName));
var iconBasePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, iconPath.Substring(1).Replace("/", "\\"), iconName);
return iconBasePath;
}
public string GetDocumentIcon(string ext)
{
string fileName = "txt.png";
switch (ext)
{
case ".ai":
fileName = "ai.png";
break;
case ".avi":
fileName = "avi.png";
break;
case ".doc":
fileName = "doc.png";
break;
case ".docx":
fileName = "doc.png";
break;
case ".fla":
fileName = "fla.png";
break;
case ".id":
fileName = "id.png";
break;
case ".jpg":
fileName = "jpg.png";
break;
case ".jpeg":
fileName = "jpeg.png";
break;
case ".pdf":
fileName = "pdf.png";
break;
case ".ppt":
fileName = "ppt.png";
break;
case ".pptx":
fileName = "ppt.png";
break;
case ".psd":
fileName = "psd.png";
break;
case ".txt":
fileName = "txt.png";
break;
case ".wav":
fileName = "wav.png";
break;
case ".xls":
fileName = "xls.png";
break;
case ".xlsx":
fileName = "xls.png";
break;
case "video":
fileName = "video.png";
break;
}
return fileName;
}
private XElement GetFullXml(string exifToolPath)
{
string args = string.Format("-X \"{0}\"", this.fullPath);
string output = RunProcess(exifToolPath, args);
output = Sanitize(output);
return new XElement("FullMetadata", XElement.Parse(output));
}
public virtual string GetCreateDate()
{
if (this.Document.Descendants(Composite + "DateTimeCreated").FirstOrDefault() != null)
return (string)this.Document.Descendants(Composite + "DateTimeCreated").FirstOrDefault();
return null;
}
public virtual string GetModifyDate()
{
return null;
}
public virtual string GetDuration()
{
if (this.Document.Descendants(Composite + "Duration").FirstOrDefault() != null)
return (string)this.Document.Descendants(Composite + "Duration").FirstOrDefault();
return null;
}
public virtual int GetImageWidth()
{
if (this.Document.Descendants(FileNamespace + "ImageWidth").FirstOrDefault() != null)
return (int)this.Document.Descendants(FileNamespace + "ImageWidth").FirstOrDefault();
return 0;
}
public virtual int GetImageHeight()
{
if (this.Document.Descendants(FileNamespace + "ImageHeight").FirstOrDefault() != null)
return (int)this.Document.Descendants(FileNamespace + "ImageHeight").FirstOrDefault();
return 0;
}
public virtual string GetImageSize()
{
if (this.Document.Descendants(Composite + "ImageSize").FirstOrDefault() != null)
return (string)this.Document.Descendants(Composite + "ImageSize").FirstOrDefault();
return null;
}
public void Dispose()
{
this.service.Dispose();
}
private string GenerateId()
{
long i = 1;
foreach (byte b in Guid.NewGuid().ToByteArray())
{
i *= ((int)b + 1);
}
return string.Format("{0:x}", i - DateTime.Now.Ticks);
}
private string RunProcess(string exifToolPath, string args)
{
if (String.IsNullOrEmpty(exifToolPath))
throw new SystemException("EXIFTool Executable Path Not Configured");
if (!System.IO.File.Exists(exifToolPath))
throw new SystemException("EXIFTool Executable Not Found: " + exifToolPath);
var process = new Process
{
StartInfo =
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
FileName = exifToolPath,
Arguments = args
}
};
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return output;
}
private string Sanitize(string s)
{
return s.Replace("&", string.Empty);
}
}
然後我創建了一個簡單的文檔類繼承文件
public class Document : File
{
private XNamespace XMPxmp = "http://ns.exiftool.ca/XMP/XMP-xmp/1.0/";
private XNamespace PDF = "http://ns.exiftool.ca/PDF/PDF/1.0/";
private XNamespace FlashPix = "http://ns.exiftool.ca/FlashPix/FlashPix/1.0/";
private XNamespace XML = "http://ns.exiftool.ca/XML/XML/1.0/";
public Document(IObjectService service, string destination, string fileName)
: base(service, destination, fileName)
{
}
public override Metadata GetMetadata(string exifToolPath)
{
var metadata = base.GetMetadata(exifToolPath);
metadata.CreateDate = this.GetCreateDate();
metadata.ModifyDate = this.GetModifyDate();
return metadata;
}
public override string GetThumbnail()
{
return base.GetThumbnail();
}
public override string GetCreateDate()
{
if (Document.Descendants(PDF + "CreateDate").FirstOrDefault() != null)
return (string)Document.Descendants(PDF + "CreateDate").FirstOrDefault();
if (Document.Descendants(XMPxmp + "CreateDate").FirstOrDefault() != null)
return (string)Document.Descendants(XMPxmp + "CreateDate").FirstOrDefault();
if (Document.Descendants(FlashPix + "CreateDate").FirstOrDefault() != null)
return (string)Document.Descendants(FlashPix + "CreateDate").FirstOrDefault();
if (Document.Descendants(XML + "CreateDate").FirstOrDefault() != null)
return (string)Document.Descendants(XML + "CreateDate").FirstOrDefault();
return base.GetCreateDate();
}
public override string GetModifyDate()
{
if (Document.Descendants(PDF + "ModifyDate").FirstOrDefault() != null)
return (string)Document.Descendants(PDF + "ModifyDate").FirstOrDefault();
if (Document.Descendants(XMPxmp + "ModifyDate").FirstOrDefault() != null)
return (string)Document.Descendants(XMPxmp + "ModifyDate").FirstOrDefault();
if (Document.Descendants(FlashPix + "ModifyDate").FirstOrDefault() != null)
return (string)Document.Descendants(FlashPix + "ModifyDate").FirstOrDefault();
if (Document.Descendants(XML + "ModifyDate").FirstOrDefault() != null)
return (string)Document.Descendants(XML + "ModifyDate").FirstOrDefault();
return base.GetModifyDate();
}
}
,然後我創建了一個複雜的圖片也繼承的類文件:
public class Image : File
{
private XNamespace PNG = "http://ns.exiftool.ca/PNG/PNG/1.0/";
private XNamespace GIF = "http://ns.exiftool.ca/GIF/GIF/1.0/";
private XNamespace IFD0 = "http://ns.exiftool.ca/EXIF/IFD0/1.0/";
private XNamespace IFD1 = "http://ns.exiftool.ca/EXIF/IFD1/1.0/";
private XNamespace BMP = "http://ns.exiftool.ca/BMP/BMP/1.0/";
private XNamespace JFIF = "http://ns.exiftool.ca/JFIF/JFIF/1.0/";
private XNamespace XMPtiff = "http://ns.exiftool.ca/XMP/XMP-tiff/1.0/";
private XNamespace XMPxmp = "http://ns.exiftool.ca/XMP/XMP-xmp/1.0/";
public Image(IObjectService service, string destination, string fileName)
: base(service, destination, fileName)
{
}
public override string GetThumbnail()
{
this.service.Download(this.destination, this.fileName); // Get our file
if (System.IO.File.Exists(this.fullPath))
{
var ext = Path.GetExtension(this.fileName);
var iconName = this.fileName.Replace(ext, "_thumb.png");
var iconPath = Path.Combine(this.destination, iconName); // get our final path
using (var original = new Bitmap(this.fullPath))
{
var thumnail = ResizeImage(300, original); // Resize our image
thumnail.Save(iconPath, System.Drawing.Imaging.ImageFormat.Png); // save the thumbnail
return iconPath;
}
}
return "";
}
public override Metadata GetMetadata(string exifToolPath)
{
var metadata = base.GetMetadata(exifToolPath);
metadata.CreateDate = this.GetCreateDate();
metadata.ModifyDate = this.GetModifyDate();
metadata.ImageWidth = this.GetImageWidth();
metadata.ImageHeight = this.GetImageHeight();
metadata.ImageSize = this.GetImageSize();
metadata.Orientation = (string)this.Document.Descendants(XMPtiff + "Orientation").FirstOrDefault();
return metadata;
}
public override string GetCreateDate()
{
if (this.Document.Descendants(XMPxmp + "CreateDate").FirstOrDefault() != null)
return (string)this.Document.Descendants(XMPxmp + "CreateDate").FirstOrDefault();
return base.GetCreateDate();
}
public override string GetModifyDate()
{
if (this.Document.Descendants(IFD0 + "ModifyDate").FirstOrDefault() != null)
return (string)Document.Descendants(IFD0 + "ModifyDate").FirstOrDefault();
if (this.Document.Descendants(XMPxmp + "ModifyDate").FirstOrDefault() != null)
return (string)this.Document.Descendants(XMPxmp + "ModifyDate").FirstOrDefault();
return base.GetModifyDate();
}
public override int GetImageWidth()
{
if (this.Document.Descendants(PNG + "ImageWidth").FirstOrDefault() != null)
return (int)this.Document.Descendants(PNG + "ImageWidth").FirstOrDefault();
if (this.Document.Descendants(GIF + "ImageWidth").FirstOrDefault() != null)
return (int)this.Document.Descendants(GIF + "ImageWidth").FirstOrDefault();
if (this.Document.Descendants(IFD0 + "ImageWidth").FirstOrDefault() != null)
return (int)this.Document.Descendants(IFD0 + "ImageWidth").FirstOrDefault();
if (this.Document.Descendants(BMP + "ImageWidth").FirstOrDefault() != null)
return (int)this.Document.Descendants(BMP + "ImageWidth").FirstOrDefault();
return base.GetImageWidth();
}
public override int GetImageHeight()
{
if (this.Document.Descendants(PNG + "ImageHeight").FirstOrDefault() != null)
return (int)this.Document.Descendants(PNG + "ImageHeight").FirstOrDefault();
if (this.Document.Descendants(GIF + "ImageHeight").FirstOrDefault() != null)
return (int)this.Document.Descendants(GIF + "ImageHeight").FirstOrDefault();
if (this.Document.Descendants(IFD0 + "ImageHeight").FirstOrDefault() != null)
return (int)this.Document.Descendants(IFD0 + "ImageHeight").FirstOrDefault();
if (this.Document.Descendants(BMP + "ImageHeight").FirstOrDefault() != null)
return (int)this.Document.Descendants(BMP + "ImageHeight").FirstOrDefault();
return base.GetImageHeight();
}
public override string GetImageSize()
{
if (this.Document.Descendants(PNG + "ImageSize").FirstOrDefault() != null)
return (string)this.Document.Descendants(PNG + "ImageSize").FirstOrDefault();
if (this.Document.Descendants(GIF + "ImageSize").FirstOrDefault() != null)
return (string)this.Document.Descendants(GIF + "ImageSize").FirstOrDefault();
if (this.Document.Descendants(IFD0 + "ImageSize").FirstOrDefault() != null)
return (string)this.Document.Descendants(IFD0 + "ImageSize").FirstOrDefault();
if (this.Document.Descendants(BMP + "ImageSize").FirstOrDefault() != null)
return (string)this.Document.Descendants(BMP + "ImageSize").FirstOrDefault();
return base.GetImageSize();
}
private int GetXResolution()
{
if (this.Document.Descendants(JFIF + "XResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(JFIF + "XResolution").FirstOrDefault();
if (this.Document.Descendants(IFD1 + "XResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(IFD1 + "XResolution").FirstOrDefault();
if (this.Document.Descendants(XMPtiff + "XResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(XMPtiff + "XResolution").FirstOrDefault();
return 0;
}
private int GetYResolution()
{
if (this.Document.Descendants(JFIF + "YResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(JFIF + "YResolution").FirstOrDefault();
if (this.Document.Descendants(IFD1 + "YResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(IFD1 + "YResolution").FirstOrDefault();
if (this.Document.Descendants(XMPtiff + "YResolution").FirstOrDefault() != null)
return (int)this.Document.Descendants(XMPtiff + "YResolution").FirstOrDefault();
return 0;
}
private string GetResolutionUnit()
{
if (this.Document.Descendants(JFIF + "ResolutionUnit").FirstOrDefault() != null)
return (string)this.Document.Descendants(JFIF + "ResolutionUnit").FirstOrDefault();
if (this.Document.Descendants(XMPtiff + "ResolutionUnit").FirstOrDefault() != null)
return (string)this.Document.Descendants(XMPtiff + "ResolutionUnit").FirstOrDefault();
return null;
}
private Stream ResizeImage(int width, System.Drawing.Image original)
{
var stream = new MemoryStream();
var ext = Path.GetExtension(this.fileName);
var image = original;
var maxHeight = original.Height;
var maxWidth = original.Width;
var b = maxHeight > maxWidth ? maxHeight : maxWidth;
var percent = (b > width) ? (width * 1.0)/b : 1.0;
maxHeight = (int)(maxHeight * percent);
maxWidth = (int)(maxWidth * percent);
if (original.Height < maxHeight && original.Width < maxWidth)
{
// do nothing
}
else
{
var cpy = new System.Drawing.Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb);
using (var gr = Graphics.FromImage(cpy))
{
gr.Clear(Color.Transparent);
// This is said to give best quality when resizing images
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.DrawImage(original,
new Rectangle(0, 0, maxWidth, maxHeight),
new Rectangle(0, 0, original.Width, original.Height),
GraphicsUnit.Pixel);
}
image = cpy;
}
switch (ext.ToLower())
{
case ".tif":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff); // save the thumbnail
break;
case ".tiff":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff); // save the thumbnail
break;
case ".bmp":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); // save the thumbnail
break;
case ".gif":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Gif); // save the thumbnail
break;
case ".jpg":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); // save the thumbnail
break;
case ".jpeg":
image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); // save the thumbnail
break;
default:
image.Save(stream, System.Drawing.Imaging.ImageFormat.Png); // save the thumbnail
break;
}
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
}
,最後我創建了一個FileFactory類,看起來像這樣:
public class FileFactory
{
public static File Get(IObjectService service, string destination, string fileName, string exifToolPath)
{
var file = new File(service, destination, fileName);
var metadata = file.GetMetadata(exifToolPath);
var mime = metadata.MIMEType;
var type = mime.ToLower().Split('/')[0];
switch(type)
{
case "image":
return file as Image;
default:
return file as Document;
}
}
}
希望現在你可以看到我想要的目的。我有4個類將繼承文件(文檔,音頻,視頻和圖像)。 這些類別中的每一個將從覆蓋方法文件。現在
,看着我廠創建通用文件類的實例,並通過檢查元數據MIMETYPE我返回實例作爲圖片或文檔,這樣在我的代碼的其他地方,當我打電話給方法GetThumbnail()它使用正確的代碼來生成該縮略圖。
你會認爲這是有效的嗎?或者你會建議一種替代方法?請幫助我:)
所以,爲了說一些有關設計模式的東西,你試圖解決什麼問題? 用於在元數據更改上創建concreate類,您可以使用觀察者模式(元數據上的通知更改事件) – Batavia
首先,我希望找到處理文件的人(特別是創建縮略圖並獲取元數據)並查明他們是否使用了設計模式。其次,我想找到一個符合我所做的命名約定:) – r3plica