2014-02-05 86 views
1

我有一個類(當前稱爲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()它使用正確的代碼來生成該縮略圖。

你會認爲這是有效的嗎?或者你會建議一種替代方法?請幫助我:)

+0

所以,爲了說一些有關設計模式的東西,你試圖解決什麼問題? 用於在元數據更改上創建concreate類,您可以使用觀察者模式(元數據上的通知更改事件) – Batavia

+0

首先,我希望找到處理文件的人(特別是創建縮略圖並獲取元數據)並查明他們是否使用了設計模式。其次,我想找到一個符合我所做的命名約定:) – r3plica

回答

1

我的答案是挑選一些東西,然後願意改變它。陷入完美的名字並沒有幫助。重命名只是一個小的重構,你的工具也能幫助你。上下文似乎是你以前沒有的。