Не System.Web заменяет HttpPostedFileBase?

Я пытаюсь переместить некоторый унаследованный код C# MVC в общую DLL. До сих пор все шло хорошо, но меня попросили, чтобы эта общая DLL никоим образом не ссылалась на System.Web.

Единственный тип, используемый в этой DLL из System.Web, — это HttpPostedFileBase:

public string ChangeAttachment(int userId, HttpPostedFileBase file)
{
    string attachmentsFolderPath = ConfigurationManager.AppSettings["AttachmentsDirectory"];
    if (!Directory.Exists(attachmentsFolderPath))
    {
        Directory.CreateDirectory(attachmentsFolderPath);
    }

    string fileTarget = Path.Combine(attachmentsFolderPath, userId.ToString() + Path.GetExtension(file.FileName));

    if (File.Exists(fileTarget))
    {
        File.Delete(fileTarget);
    }

    file.SaveAs(fileTarget);

    return fileTarget;
}

Как видите, здесь не нужны никакие функции HTTP или Web, так как используются только его члены FileName и SaveAs().

Есть ли замена, которую я могу легко преобразовать в HttpPostedFileBase в вызывающем объекте, чтобы все, что мне нужно было передать в качестве параметра, это не веб-файл?

Примечание. HttpPostedFileBase наследуется напрямую от System.Object, а не от какого-либо файлового класса.


person datps    schedule 27.03.2016    source источник
comment
Разве вы не можете передать и использовать FileName для копирования вложения вместо использования метода SaveAs?   -  person Mehrzad Chehraz    schedule 27.03.2016
comment
@MehrzadChehraz Очевидно, он не может. Обратите внимание на file.SaveAs(fileTarget) в его исходном коде: он также передает поток.   -  person Not So Sharp    schedule 27.03.2016
comment
@NotSoSharp, тогда ему нужно определить интерфейс.   -  person Mehrzad Chehraz    schedule 27.03.2016


Ответы (2)


HttpPostedFileBase — это абстрактный класс. Итак, проблема в том, что вы на самом деле не заменяете этот класс, вы заменяете HttpPostedFileWrapper, который является реализацией. (Это не то, от чего наследуется класс, это то, что наследуется от него.)

HttpPostedFileWrapper, в свою очередь, ссылается на другие System.Web классы, такие как HttpInputStream и «HttpPostedFile».

Таким образом, вы не можете заменить его. Возможно, вас просили не ссылаться на System.Web, потому что вы переносили устаревший код, не связанный напрямую с веб-функциями, такими как бизнес-логика. Если вы не можете просто полностью исключить код, возможно, вы могли бы исключить его из новой сборки, которую вы создаете, а затем иметь другую сборку, которая ссылается на System.Web. Если им не нужна эта конкретная функциональность, они ссылаются только на одну сборку, но если им это нужно, они также могут добавить вторую сборку, которая ссылается на System.Web.

person Scott Hannen    schedule 27.03.2016
comment
Спасибо. Есть ли конструктор FileStream, который принимает производную от HttpPostedFileWrapper в качестве параметра? - person datps; 28.03.2016
comment
Нет. Вы можете просмотреть все конструкторы здесь: msdn.microsoft.com/en-us/library/. (Я постоянно использую документацию MSDN для классов и методов.) - person Scott Hannen; 28.03.2016

Если вы не хотите ссылаться на System.Web и хотите использовать Сохранить как, вы можете определить интерфейс, а также оболочку для создания ссылки. Однако это не очень простой подход:

//// Second assembly (Without referencing System.Web):
// An interface to link the assemblies without referencing to System.Web
public interface IAttachmentFile {
    void SaveAs(string FileName);
}
..
..
// Define ChangeAttachment method
public string ChangeAttachment(int userId, IAttachmentFile attachmentFile) { 
   string attachmentsFolderPath = ConfigurationManager.AppSettings["AttachmentsDirectory"];
   if (!Directory.Exists(attachmentsFolderPath)) {
        Directory.CreateDirectory(attachmentsFolderPath);
   }
   string fileTarget = Path.Combine(
        attachmentsFolderPath, 
        userId.ToString() + Path.GetExtension(file.FileName) 
   );
   if (File.Exists(fileTarget)) {
       File.Delete(fileTarget);
   }
   // This call leads to calling HttpPostedFileBase.SaveAs
   attachmentFile.SaveAs(fileTarget);
   return fileTarget;
}

//// First assembly (Referencing System.Web):
// A wrapper class around HttpPostedFileBase to implement IAttachmentFile   
class AttachmentFile : IAttachmentFile {
    private readonly HttpPostedFileBase httpPostedFile;
    public AttachmentFile(HttpPostedFileBase httpPostedFile) {
        if (httpPostedFile == null) {
            throw new ArgumentNullException("httpPostedFile");
        }
        this.httpPostedFile = httpPostedFile;
    }
    // Implement IAttachmentFile interface
    public SaveAs(string fileName) {
        this.httpPostedFile.SaveAs(fileName);
    }
}
..
..
// Create a wrapper around the HttpPostedFileBase object
var attachmentFile = new AttachmentFile(httpPostedFile);

// Call the ChangeAttachment method
userManagerObject.ChangeAttachment(userId, attachmentFile);
person Mehrzad Chehraz    schedule 27.03.2016
comment
Спасибо. К сожалению, интерфейс мне здесь не поможет, потому что мне действительно нужен преобразователь из HttpPostedFileBase/HttpPostedFileWrapper в двоичный сериализатор, аналогичный описанному в этом ответе или этой статьи. - person datps; 28.03.2016
comment
@datps Я действительно не понимаю, какое отношение ваш вопрос имеет к двоичному сериализатору. Возможно, вам потребуется обновить его для уточнения. - person Mehrzad Chehraz; 28.03.2016