我了解 HttpPostedFileBase 和 HttpPostedFileWrapper 之间的关系,就两者的需求而言(即在单元测试/模拟中)。但是,为什么当我在 HttpPostedFileBase 的返回值上设置断点时,它是否显示为 HttpPostedFileWrapper?
此外,HttpPostedFileBase 没有实现 ContentType 属性。那么,当我的代码仅 引用HttpPostedFileBase 而不是HttpPostedFileWrapper 时,为什么它会返回一个值?这是什么诡计?
编辑#1:
感谢@lawliet29 的精彩回复。我已经按照建议写出了结构。
public sealed class MyHttpPostedFile
{
public string ContentType { get { return "123"; } }
}
public abstract class MyHttpPostedFileBase
{
}
public class MyHttpPostedFileWrapper : MyHttpPostedFileBase
{
private MyHttpPostedFile _myHttpPostedFile;
public MyHttpPostedFileWrapper(MyHttpPostedFile myHttpPostedFile) {
_myHttpPostedFile = myHttpPostedFile;
}
public string ContentType { get { return _myHttpPostedFile.ContentType; } }
}
为了让它工作,我需要像这样传递参数:
GetFiles(new MyHttpPostedFileWrapper(new MyHttpPostedFile());
这似乎是我质疑的诡计存在的地方。 .NET 如何知道传递给它的字节是 MyHttpPostedFile 类型的类,并且它应该获取该对象并将其作为参数传递到我的构造函数中?
编辑#2:
我没有意识到 ASP.NET MVC 绑定(bind)器除了通过传递这些更高级别的对象来传递字节之外还能做更多的事情。这就是我想知道的诡计!感谢您的精彩回复。
最佳答案
其实很简单。 HttpPostedFileBase 是一个抽象类,仅用于被派生的目的。它被用来使密封类 HttpPostedFile 中的某些东西可以模拟。
然而,在现实生活中,HttpPostedFile 是处理已发布文件的工具,为了保持一致,创建了 HttpPostedFileWrapper。此类通过包装 HttpPostedFile 为 HttpPostedFileBase 提供实现。
所以HttpPostedFileBase是一个统一的抽象,HttpPostedFile是一个表示posted文件的类,HttpPostedFileWrapper是HttpPostedFileBase的实现,它包装了HttpPostedFile。 HttpPostedFileWrapper 的 ContentType 属性的实现从底层 HttpPostedFile 读取内容类型。
编辑:某种解释
ASP.NET MVC 接收到一个文件,并且在其下方的某处创建了一个 HttpPostedFile 实例,因为这是自 .NET Framework 1.0 以来的工作方式。 HttpPostedFile 的定义如下所示:
public sealed class HttpPostedFile
这基本上意味着它不能被继承,也不能为单元测试而模拟。
为解决此问题,ASP.NET MVC 开发人员创建了一个可模拟的抽象 - HttpPostedFileBase,其定义如下:
public abstract class HttpPostedFileBase
现在,您可以定义 MVC 操作,以便它们接受 HttpPostedFileBase 而不是不可模拟的 HttpPostedFile:
[HttpPost]
public ActionResult PostFile(HttpPostedFileBase file)
{
// some logic here...
}
问题是,在下面的某个地方,表示已发布文件的唯一方法是老式的死板 HttpPostedFile。因此,为了支持这种抽象,MVC 开发人员创建了一个名为 HttpPostedFileWrapper 的装饰器,大致如下所示:
public class HttpPostedFileWrapper : HttpPostedFileBase
{
private HttpPostedFile _httpPostedFile;
public HttpPostedFileWrapper(HttpPostedFile httpPostedFile) {
_httpPostedFile = httpPostedFile;
}
public string ContentType { get { return _httpPostedFile.ContentType; } }
// implementation of other HttpPostedFileBase members
}
因此,现在 HttpPostedFileWrapper 是您在使用已发布的文件执行真正的 HTTP POST 请求时实际得到的。由于多态性,您可以将派生类的实例 - HttpPostedFileWrapper - 传递给方法接受基类 - HttpPostedFileBase。
一直以来,您都可以创建自己的模拟实现,比如说,看起来就像正在发布的视频文件。你会这样做
public class MockPostedVideoFile : HttpPostedFileBase
{
public string ContentType { get { return "video/mp4"; } }
// rest of implementation here
}
另一个编辑: HttpPostedFile 的实际实例化全部由 System.Web 为您处理。 ASP.NET MVC 绑定(bind)器对于发布的表单数据非常智能。它会自动检测到某些 post 值实际上是文件的字节,因此为了正确表示它们,它可以使用 System.Web 框架中的旧内容来创建一个实例 HttpPostedFile。
这里的要点是 - 您无需担心。这里的幕后发生了很多事情,我们真的需要感谢 ASP.NET MVC 团队将所有这些低级别的事情抽象化。
您唯一需要担心的地方是单元测试。在您的测试中,您可以使用模拟实现来调用您的操作,如下所示:
myController.PostFile(new MockPostedVideoFile())
关于c# - HttpPostedFileBase 与 HttpPostedFileWrapper 的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24910982/
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
我想合并多个事件记录关系例如,apple_companies=Company.where("namelike?","%apple%")banana_companies=Company.where("namelike?","%banana%")我想结合这两个关系。不是合并,合并是apple_companies.merge(banana_companies)=>Company.where("namelike?andnamelike?","%apple%","%banana%")我要Company.where("名字像?还是名字像?","%apple%","%banana%")之后,我会写代
我有一个简单的问题,与关联有关。我有一个书的模型,它有_onereservation。预订属于_书本。我想在预订Controller的创建方法中确保在预订时没有预订一本书。换句话说,我需要检查该书是否存在任何其他预订。我该怎么做?编辑:Aaa我做到了,感谢大家的提示,学到了一些新东西。当我尝试提供的解决方案时,出现no_method错误或nil_class等。这让我开始思考,我尝试处理的对象根本不存在。Krule给了我使用book.find的想法,所以我尝试使用它。最终我得到了它的工作:book=Book.find_by_id(reservation_params[:book_id])
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj