Сомнение в создании экземпляра дочернего класса абстрактного класса - PullRequest
1 голос
/ 23 июля 2011

Я работаю над проектом ASP.Net MVC с LinqToSQL и многослойным.Пользователи будут выгружать файлы, в основном файлы Excel и Access, и мой сервисный уровень выполнит всю его проверку и другие вещи.

Я думал о реализации абстрактного класса с именем «UploadManager» и двух дочерних классов: «UploadExcel»и «UploadAccess».Некоторые методы будут общими для обоих классов, например «SaveFile» и «DeleteFile».Но некоторые другие методы будут ограничены определенным дочерним классом, таким как «ValidateWorksheet», который будет принадлежать только классу «UploadExcel».

Я проектировал что-то вроде этого:

    public abstract class UploadManager
    {
        protected void SaveFile(string fileName)
        {
             //Implement
        }

        protected void DeleteFile(string fileName)
        {
             //Implement
        }
    }

   public class UploadExcel : UploadManager
   {
      private bool ValidateWorksheet()
      {
         //Implement
      }
   }

   public class UploadAccess : UploadManager
   {
      private bool ValidateSomethingAboutAccess()
      {
         //Implement
      }
   }

Я тоже думал об использовании интерфейсов.Но мое главное сомнение в том, как я могу узнать, какой дочерний класс мне нужно создать?Если загруженный файл является файлом Excel, это будет «new UploadExcel()», а если это файл Access, это будет «new UploadAccess()».

Есть ли способ сделать это?Есть ли способ лучше?Я немного потерян с этим ...

Спасибо заранее !!

Ответы [ 5 ]

2 голосов
/ 23 июля 2011

Может сделать что-то вроде этого, псевдокод :

Первый:

public abstract class UploadManager
{
   public void SaveFile(string fileName){ //uploading file }
   public abstract bool CanAccept(string sFileName); //abstract

    protected void DeleteFile(string fileName)
    {
       //Implement
    }
}

Вторая конкретная реализация:

 public class UploadExcel : UploadManager
   {
      public override bool CanAccept(string sFileName) {

           //if Excel file return true, else false
      }

      private bool ValidateWorksheet()
      {
         //Implement
      }
   }

   public class UploadAccess : UploadManager
   {
       public override bool CanAccept(string sFileName) {

           //if Access file return true, else false
      }
      private bool ValidateSomethingAboutAccess()
      {
         //Implement
      }
   }

Где-то в коде у вас есть коллекция:

List<UploadManager> managers = new List<UploadManager>{ new UploadExcel(), new UploadAccess()};



//at the time decide to send a file (sFileName): 
UploadManager myUploadManager = managers.Find(manager=>{return manager.CanAccept(sFileName);});
myUploadManager.SaveFile(sFileName); //call concrete implementaiton for that specific file

Код работает только с типом UploadManager, поэтому вы создаете определенный слой абстракции поверх любой конкретной реализации для любого загрузчика типов файлов.

Привет.

Готово.

1 голос
/ 23 июля 2011
1 голос
/ 23 июля 2011

Основная идея состоит в том, чтобы дополнить метод validate как abstract в базовом классе.

При создании экземпляра вам нужно беспокоиться только о дочернем классе, в остальном вы имеете дело только с методами базового класса:

string fileName = ...;  // from your request somehow

UploadManager manager = null;  // note the type of manager, no var

if (System.IO.Path.GetExtension(filename).LowerCase().StartsWith("xls"))    
   manager = new UploadExcel ();  
else
   ...   

manager.Validate();  // calls the Excel or the Access override

И ваши классы будут выглядеть больше как

public abstract class UploadManager
{
    // SaveFile, DeleteFile

    public abstract bool Validate();
}


public class UploadExcel : UploadManager
{
      public override bool Validate()
      {
          // ...
          return ValidateWorksheet();
      }

      private bool ValidateWorksheet()
      {
         //Implement
      }
}
0 голосов
/ 23 июля 2011

Вы можете определить интерфейс

public interface IUserDataManager
{
    void SaveFile();
    void DeleteFile();
    void Validate();
}

Тогда абстрактный класс и двое детей

public abstract class UserDataManager : IUserDataManager
{
    private readonly string filename;

    protected UserDataManager(string filename)
    {
        this.filename = filename;
    }

    public void SaveFile()
    {
        Console.WriteLine("File saved as: " + filename);
    }

    public void DeleteFile()
    {
        Console.WriteLine("File deleted: " + filename);
    }

    public abstract void Validate();
}

public class AccessUserDataManager : UserDataManager
{
    public AccessUserDataManager(string filename) : base(filename) { }

    public override void Validate()
    {
        Console.WriteLine("Access validated");
    }
}

public class ExcellUserDataManager : UserDataManager
{
    public ExcellUserDataManager(string filename) : base(filename) { }

    public override void Validate()
    {
        Console.WriteLine("Excel validated");
    }
}

И вот как это использовать

class Program
{
    static void Main(string[] args)
    {
        IUserDataManager mgr = new AccessUserDataManager("access.db");
        mgr.Validate();
        mgr.SaveFile();
        mgr.DeleteFile();

        mgr = new ExcellUserDataManager("excel.xlsx");
        mgr.Validate();
        mgr.SaveFile();
        mgr.DeleteFile();

        Console.ReadLine();
    }
}
0 голосов
/ 23 июля 2011

Исходя из моего понимания вашего вопроса, у вас может быть кеш менеджеров закачки, чтобы при выборе пользователем загружать файл вы могли получить менеджера, соответствующего расширению файла.т.е.

// Cache of upload managers keyed by their associated file extension
private Dictionary<string, UploadManager> mManagers;

    // ... Add managers to cache in constructor ...

public void Upload(string filename)
{
    string extension = System.IO.Path.GetExtension(filename);

    // See if we have a manager for this extension
    UploadManager manager;
    if(mManagers.TryGetValue(extension, out manager))
    {
        // Validate the file
        // Note: This will call an abstract method in the UploadManager base
        //   class that will be defined in the child classes.
        manager.Validate(filename);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...