开发者

Doubt about instantiating child class of an abstract class

开发者 https://www.devze.com 2023-03-22 16:09 出处:网络
I\'m on a ASP.Net MVC project with LinqToSQL and multilayer. Users cand upload files, basically Excel and Access file and my service layer will do all of its validatio开发者_如何学JAVAn and other stuf

I'm on a ASP.Net MVC project with LinqToSQL and multilayer. Users cand upload files, basically Excel and Access file and my service layer will do all of its validatio开发者_如何学JAVAn and other stuff.

I was thinking about implement an abstract class named "UploadManager" and 2 child classes: "UploadExcel" and "UploadAccess". Some methods will be common to both classes, such as "SaveFile" and "DeleteFile". But, some other methods will be restricted to an especific child class, such as "ValidateWorksheet" that will belong to "UploadExcel" class only.

I was designing something like this:

    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
      }
   }

I was thinking about using Interfaces too. But, my main doubt is how can I know which child class I have to instantiate? If uploaded file is an Excel file, it will be "new UploadExcel()" and if it is an Access file, it will be "new UploadAccess()".

Is there a way to accomplish this? Is there a better way? I'm some kinda lost with this...

Thanks in advance!!


Could do something like this, a pseudocode:

First:

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

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

Second concrete implementation:

 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
      }
   }

Somewhere in the code you have a collection:

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

The code works only with UploadManager type, so you create definit abstraction layer over any concrete implementation for any file type uploader you want.

Regards.

Done.


The basic idea would be to inplement the validate method as abstract in the base class.

You then only have to worry about the child class when instantiating, for the rest you only deal with the base class methods:

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

And your classes would look more like

public abstract class UploadManager
{
    // SaveFile, DeleteFile

    public abstract bool Validate();
}


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

      private bool ValidateWorksheet()
      {
         //Implement
      }
}


I believe what you're looking for is the Abstract factory design pattern


Based on my understanding of your question, you could have a cache of upload managers so that when the user selects to upload the file, you can get the manager relevant to the file extension. i.e.

// 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);
    }
}


You can define an interface

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

Then abstract class and two children

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");
    }
}

And this is how to use it

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

精彩评论

暂无评论...
验证码 换一张
取 消