简体   繁体   English

怀疑实例化抽象类的子类

[英]Doubt about instantiating child class of an abstract class

I'm on a ASP.Net MVC project with LinqToSQL and multilayer. 我正在使用LinqToSQL和多层的ASP.Net MVC项目。 Users cand upload files, basically Excel and Access file and my service layer will do all of its validation and other stuff. 用户可以上传文件,基本上是Excel和Access文件,我的服务层将完成所有的验证和其他工作。

I was thinking about implement an abstract class named "UploadManager" and 2 child classes: "UploadExcel" and "UploadAccess". 我正在考虑实现一个名为“UploadManager”的抽象类和2个子类:“UploadExcel”和“UploadAccess”。 Some methods will be common to both classes, such as "SaveFile" and "DeleteFile". 有些方法对两个类都是通用的,例如“SaveFile”和“DeleteFile”。 But, some other methods will be restricted to an especific child class, such as "ValidateWorksheet" that will belong to "UploadExcel" class only. 但是,其他一些方法将仅限于特定的子类,例如仅属于“UploadExcel”类的“ValidateWorksheet”。

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. 我也在考虑使用Interfaces。 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() ". 如果上传的文件是Excel文件,则它将是“ new UploadExcel() ”,如果它是Access文件,则它将是“ 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. 该代码仅适用于UploadManager类型,因此您可以为任何所需的文件类型上传器创建任何具体实现的definit抽象层。

Regards. 问候。

Done. 完成。

The basic idea would be to inplement the validate method as abstract in the base class. 基本思想是将validate方法作为基类中的abstract方法。

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

我相信你所寻找的是抽象的工厂设计模式

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. 根据我对您的问题的理解,您可以拥有一个上传管理器缓存,以便在用户选择上传文件时,您可以获得与文件扩展名相关的管理器。 ie

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM