2010-06-16 12 views
0

J'essaie d'apprendre des motifs et j'ai un travail qui crie pour un motif, je le sais juste mais je ne peux pas le comprendre. Je sais que le type de filtre est quelque chose qui peut être abstrait et éventuellement comblé. Je ne suis pas à la recherche d'un CODE REWRITE JUSTE SUGGESTIONS. Je ne cherche pas quelqu'un pour faire mon travail. Je voudrais savoir comment les modèles pourraient être appliqués à cet exemple.Bridge ou Factory et comment

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 
using System.IO; 
using System.Xml; 
using System.Text.RegularExpressions; 

namespace CopyTool 
{ 
    class CopyJob 
    { 
     public enum FilterType 
     { TextFilter, RegExFilter, NoFilter } 
     public FilterType JobFilterType { get; set; } 

     private string _jobName; 
     public string JobName { get { return _jobName; } set { _jobName = value; } } 

     private int currentIndex; 
     public int CurrentIndex { get { return currentIndex; } } 

     private DataSet ds; 

     public int MaxJobs { get { return ds.Tables["Job"].Rows.Count; } } 

     private string _filter; 
     public string Filter { get { return _filter; } set { _filter = value; } } 

     private string _fromFolder; 
     public string FromFolder 
     { 
      get { return _fromFolder; } 
      set 
      { 
       if (Directory.Exists(value)) 
       { _fromFolder = value; } 
       else 
       { throw new DirectoryNotFoundException(String.Format("Folder not found: {0}", value)); } 
      } 
     } 

     private List<string> _toFolders; 
     public List<string> ToFolders { get { return _toFolders; } } 

     public CopyJob() 
     { 
      Initialize(); 
     } 

     private void Initialize() 
     { 
      if (ds == null) 
      { ds = new DataSet(); } 
      ds.ReadXml(Properties.Settings.Default.ConfigLocation); 
      LoadValues(0); 
     } 

     public void Execute() 
     { 
      ExecuteJob(FromFolder, _toFolders, Filter, JobFilterType); 
     } 

     public void ExecuteAll() 
     { 
      string OrigPath; 
      List<string> DestPaths; 
      string FilterText; 
      FilterType FilterWay; 
      foreach (DataRow rw in ds.Tables["Job"].Rows) 
      { 
       OrigPath = rw["FromFolder"].ToString(); 
       FilterText = rw["FilterText"].ToString(); 
       switch (rw["FilterType"].ToString()) 
       { 
        case "TextFilter": 
         FilterWay = FilterType.TextFilter; 
         break; 
        case "RegExFilter": 
         FilterWay = FilterType.RegExFilter; 
         break; 
        default: 
         FilterWay = FilterType.NoFilter; 
         break; 
       } 
       DestPaths = new List<string>(); 
       foreach (DataRow crw in rw.GetChildRows("Job_ToFolder")) 
       { 
        DestPaths.Add(crw["FolderPath"].ToString()); 
       } 
       ExecuteJob(OrigPath, DestPaths, FilterText, FilterWay); 
      } 
     } 

     private void ExecuteJob(string OrigPath, List<string> DestPaths, string FilterText, FilterType FilterWay) 
     { 
      FileInfo[] files; 
      switch (FilterWay) 
      { 
       case FilterType.RegExFilter: 
        files = GetFilesByRegEx(new Regex(FilterText), OrigPath); 
        break; 
       case FilterType.TextFilter: 
        files = GetFilesByFilter(FilterText, OrigPath); 
        break; 
       default: 
        files = new DirectoryInfo(OrigPath).GetFiles(); 
        break; 
      } 
      foreach (string fld in DestPaths) 
      { 
       CopyFiles(files, fld); 
      } 
     } 

     public void MoveToJob(int RecordNumber) 
     { 
      Save(); 
      LoadValues(RecordNumber - 1); 
     } 

     public void AddToFolder(string folderPath) 
     { 
      if (Directory.Exists(folderPath)) 
      { _toFolders.Add(folderPath); } 
      else 
      { throw new DirectoryNotFoundException(String.Format("Folder not found: {0}", folderPath)); } 
     } 

     public void DeleteToFolder(int index) 
     { 
      _toFolders.RemoveAt(index); 
     } 

     public void Save() 
     { 
      DataRow rw = ds.Tables["Job"].Rows[currentIndex]; 
      rw["JobName"] = _jobName; 
      rw["FromFolder"] = _fromFolder; 
      rw["FilterText"] = _filter; 
      switch (JobFilterType) 
      { 
       case FilterType.RegExFilter: 
        rw["FilterType"] = "RegExFilter"; 
        break; 
       case FilterType.TextFilter: 
        rw["FilterType"] = "TextFilter"; 
        break; 
       default: 
        rw["FilterType"] = "NoFilter"; 
        break; 
      } 
      DataRow[] ToFolderRows = ds.Tables["Job"].Rows[currentIndex].GetChildRows("Job_ToFolder"); 
      for (int i = 0; i <= ToFolderRows.GetUpperBound(0); i++) 
      { 
       ToFolderRows[i].Delete(); 
      } 
      foreach (string fld in _toFolders) 
      { 
       DataRow ToFolderRow = ds.Tables["ToFolder"].NewRow(); 
       ToFolderRow["JobId"] = ds.Tables["Job"].Rows[currentIndex]["JobId"]; 
       ToFolderRow["Job_Id"] = ds.Tables["Job"].Rows[currentIndex]["Job_Id"]; 
       ToFolderRow["FolderPath"] = fld; 
       ds.Tables["ToFolder"].Rows.Add(ToFolderRow); 
      } 
     } 

     public void Delete() 
     { 
      ds.Tables["Job"].Rows.RemoveAt(currentIndex); 
      LoadValues(currentIndex++); 
     } 

     public void MoveNext() 
     { 
      Save(); 
      currentIndex++; 
      LoadValues(currentIndex); 
     } 

     public void MovePrevious() 
     { 
      Save(); 
      currentIndex--; 
      LoadValues(currentIndex); 
     } 

     public void MoveFirst() 
     { 
      Save(); 
      LoadValues(0); 
     } 

     public void MoveLast() 
     { 
      Save(); 
      LoadValues(ds.Tables["Job"].Rows.Count - 1); 
     } 

     public void CreateNew() 
     { 
      Save(); 
      int MaxJobId = 0; 
      Int32.TryParse(ds.Tables["Job"].Compute("Max(JobId)", "").ToString(), out MaxJobId); 
      DataRow rw = ds.Tables["Job"].NewRow(); 
      rw["JobId"] = MaxJobId + 1; 
      ds.Tables["Job"].Rows.Add(rw); 
      LoadValues(ds.Tables["Job"].Rows.IndexOf(rw)); 
     } 

     public void Commit() 
     { 
      Save(); 
      ds.WriteXml(Properties.Settings.Default.ConfigLocation); 
     } 

     private void LoadValues(int index) 
     { 
      if (index > ds.Tables["Job"].Rows.Count - 1) 
      { currentIndex = ds.Tables["Job"].Rows.Count - 1; } 
      else if (index < 0) 
      { currentIndex = 0; } 
      else 
      { currentIndex = index; } 
      DataRow rw = ds.Tables["Job"].Rows[currentIndex]; 
      _jobName = rw["JobName"].ToString(); 
      _fromFolder = rw["FromFolder"].ToString(); 
      _filter = rw["FilterText"].ToString(); 
      switch (rw["FilterType"].ToString()) 
      { 
       case "TextFilter": 
        JobFilterType = FilterType.TextFilter; 
        break; 
       case "RegExFilter": 
        JobFilterType = FilterType.RegExFilter; 
        break; 
       default: 
        JobFilterType = FilterType.NoFilter; 
        break; 
      } 
      if (_toFolders == null) 
       _toFolders = new List<string>(); 
      _toFolders.Clear(); 
      foreach (DataRow crw in rw.GetChildRows("Job_ToFolder")) 
      { 
       AddToFolder(crw["FolderPath"].ToString()); 
      } 
     } 

     private static FileInfo[] GetFilesByRegEx(Regex rgx, string locPath) 
     { 
      DirectoryInfo d = new DirectoryInfo(locPath); 
      FileInfo[] fullFileList = d.GetFiles(); 
      List<FileInfo> filteredList = new List<FileInfo>(); 
      foreach (FileInfo fi in fullFileList) 
      { 
       if (rgx.IsMatch(fi.Name)) 
       { 
        filteredList.Add(fi); 
       } 
      } 
      return filteredList.ToArray(); 
     } 

     private static FileInfo[] GetFilesByFilter(string filter, string locPath) 
     { 
      DirectoryInfo d = new DirectoryInfo(locPath); 
      FileInfo[] fi = d.GetFiles(filter); 
      return fi; 
     } 

     private void CopyFiles(FileInfo[] files, string destPath) 
     { 
      foreach (FileInfo fi in files) 
      { 
       bool success = false; 
       int i = 0; 
       string copyToName = fi.Name; 
       string copyToExt = fi.Extension; 
       string copyToNameWithoutExt = Path.GetFileNameWithoutExtension(fi.FullName); 
       while (!success && i < 100) 
       { 
        i++; 
        try 
        { 
         if (File.Exists(Path.Combine(destPath, copyToName))) 
          throw new CopyFileExistsException(); 
         File.Copy(fi.FullName, Path.Combine(destPath, copyToName)); 
         success = true; 
        } 
        catch (CopyFileExistsException ex) 
        { 
         copyToName = String.Format("{0} ({1}){2}", copyToNameWithoutExt, i, copyToExt); 
        } 
       } 
      } 
     } 
    } 
    public class CopyFileExistsException : Exception 
    { 
     public string Message; 
    } 

} 
+0

Pourriez-vous expliquer la nature du problème et l'intention du code? – SWeko

+2

Quel est le problème que vous essayez de résoudre? Les patterns sont là pour résoudre des problèmes, ne pas être giflés sur un ancien code juste parce que vous voulez utiliser 'patterns '. – Oded

+0

Chris ... vous pourriez avoir une meilleure réponse si vous choisissez une pièce que vous aimeriez voir refactorisée. C'est le tout "Comment manges-tu un éléphant?" problème. Personne ne veut réécrire tout votre bruit juste pour donner un aperçu de ce qui pourrait être fait différent. –

Répondre

6

Ce code est également "criant" pour être décomposé en objets plus petits et plus spécialisés.

Votre objet CopyJob semble être plus un gestionnaire d'une liste de travaux. Je changerais peut-être le nom de ceci en CopyJobManager ou quelque chose. Vous pourriez alors avoir CopyJob comme classe de base pour les différents types de filtres. Le code commun, Execute() par exemple, serait défini dans la classe de base, et le comportement personnalisé, Filtrage par exemple, serait géré dans les classes dérivées. Vous auriez un TextFilterCopyJob, un RegExFilterCopyJob et un NoFilterCopyJob. Lorsque le motif Factory peut entrer en jeu, c'est lorsque vous créez une liste de CopyJobs. Vous pourriez avoir un objet CopyJobFactory qui prend une ligne de votre jeu de données et renvoie la version enfant appropriée de CopyJob. CopyJobManager effectue alors ses opérations sur une liste de CopyJobs au lieu d'une liste de lignes de dataset.

0

Il n'y a rien de mal à utiliser une instruction switch comme vous l'avez fait. Il ne crie pas pour n'importe quel modèle de conception autre que celui que vous pouvez mettre dans une fonction de sorte que vous n'ayez pas le même commutateur deux fois.

Le commutateur sera plus rapide que l'utilisation de la réflexion, et le problème que vous essayez de résoudre ne nécessite pas vraiment le modèle d'usine.

0

est ici une partie de ce que je faisais pour mettre en œuvre un modèle d'usine

D'abord, je créé une interface pour le filtre:

interface IFileFilter 
{ 
    string GetFilterName(); 
    string GetFilterReadableName(); 
    FileInfo[] GetFilteredFiles(string path, string filter); 
} 

alors je créé des classes sous-filtre pour cette interface:

class RegExFileFilter : IFileFilter 

{ 
    #region IFileFilter Members 

    public string GetFilterName() 
    { 
     return "RegExFilter"; 
    } 

    public string GetFilterReadableName() 
    { 
     return "RegEx Filter"; 
    } 

    public FileInfo[] GetFilteredFiles(string path, string filter) 
    { 
     DirectoryInfo d = new DirectoryInfo(path); 
     FileInfo[] fullFileList = d.GetFiles(); 
     List<FileInfo> filteredList = new List<FileInfo>(); 
     Regex rgx = new Regex(filter); 
     foreach (FileInfo fi in fullFileList) 
     { 
      if (rgx.IsMatch(fi.Name)) 
      { 
       filteredList.Add(fi); 
      } 
     } 
     return filteredList.ToArray(); 
    } 

    #endregion 
} 
class TextFileFilter : IFileFilter 
{ 
    #region IFileFilter Members 

    public string GetFilterName() 
    { 
     return "TextFilter"; 
    } 

    public string GetFilterReadableName() 
    { 
     return "Text Filter"; 
    } 

    public FileInfo[] GetFilteredFiles(string path, string filter) 
    { 
     DirectoryInfo d = new DirectoryInfo(path); 
     FileInfo[] fi = d.GetFiles(filter); 
     return fi; 
    } 

    #endregion 
} 
class NoFileFilter : IFileFilter 
{ 
    #region IFileFilter Members 

    public string GetFilterName() 
    { 
     return "TextFilter"; 
    } 

    public string GetFilterReadableName() 
    { 
     return "Text Filter"; 
    } 

    public FileInfo[] GetFilteredFiles(string path, string filter) 
    { 
     DirectoryInfo d = new DirectoryInfo(path); 
     FileInfo[] fi = d.GetFiles(filter); 
     return fi; 
    } 

    #endregion 
} 

Ensuite, je créé une usine:

public static IFileFilter FileFilter(string filterName) 
{ 
    switch (filterName) 
    { 
     case "Text Filter": 
      return new TextFileFilter(); 
     case "RegEx Filter": 
      return new RegExFileFilter(); 
     default: 
      return new NoFileFilter(); 
    } 
} 
0

je suggère ce qui suit:

refactoring les instructions switch (comme @Jordan mentionné)

Ajouter une méthode d'extension pour convertir le ENUM FilterType en un int et sauf que la base de données plutôt que d'une chaîne. Par exemple.

public static class FilterTypeExtensions 
{ 
    public static int AsNumeric(this FilterType filterType) 
    { 
     return (int)filterType; 
    } 
} 

Comme un point mineur, les entretoises sont d'une seule ligne horrible, soit laisser tomber les entretoises ou utiliser espacement/indentation correspondant. :)

1

Chaque fois que je vois Swithcs ou des briques de Ifs, je saute à la conclusion qu'au moins un schéma de stratégie pourrait être créé.

une manière propre et facile à installer un, est d'utiliser un dictionnaire <>

dans votre cas vous allez vouloir une valeur clé sur la base filterName vos affaires concernent, et la valeur sera une nouvelle objet des filtres.

maintenant vous pouvez simplement donner la chaîne à la méthode TryGetValue des dictionnaires et lui faire récupérer l'objet de filtre correct pour vous, boom!

Maintenant, vous pouvez encapsuler le mappage des filtres < -> Strings, et garder la logique et l'utilisation des filtres d'avoir à voir la logique de récupération de l'objet correct!