我正在尝试在MVC应用程序中使用基于接口的方法。但是,我无法将我的模型(从表单提交接收到MVC操作)传递给方法,而是抛出错误说
无法转换为Foo< Bar>到IFoo< IBar>
编辑:对于那些在我有机会根据评论更新它之前粗略删除我的完整问题的人是我发布的代码项目问题的完全重复,并认为它会让你的生活更容易阅读而不是这里。
大家好,
自从我在这里发布以来已经有一段时间了,但我有一点母马,不能为我的生活记住我做错了什么。我很确定这很简单,所以希望你能提供帮助。
我有以下(近似示例):
public interface IFoo<T>
{ //...some other properties....
List<T> Bars {get;set;}
}
public interface IBar
{ //...some properties...
}
public class Foo : IFoo<Bar>
{ //...some properties...
List<Bar> Bars {get;set;}
}
public class Bar : IBar
{ //...some properties...
}
然后我有一个看起来有点像这样的助手类:
public interface IHelper
{
bool DoSomething(IFoo<IBar> model, string path);
}
public class Helper : IHelper
{
public bool DoSomething(IFoo<IBar> model, string path)
{
//..Save model to path
return true;
}
}
所以,我遇到的问题是当我尝试将Foo的实例传递给我的帮助器方法时,我得到错误: Argumet类型'Foo'不能分配给参数类型'IFoo&lt; IBar&gt;'
我不确定为什么会收到此错误,因为Foo继承自IFoo,而Bar继承自IBar。
其他信息
这就是Foo类最初的填充方式。这是来自网页的表单提交。如果我试图将Foo声明为Foo:IFoo&lt; IBar&gt;我收到错误: 无法创建接口的实例。 提交表格。这是MVC生成的错误。因此,使用IFoo&lt; Bar&gt;
将Foo定义如上
[HttpPost]
public ActionResult RequestSubmission(Foo model)
{
if (ModelState.IsValid)
{
helper.DoSomething(model, Server.MapPath("/Assets/Template.docx"));
return Json(new {IsSuccess=true});
}
return PartialView("Form", model);
}
范围
此项目是一个没有身份验证的基本MVC5项目。 我有一个控制器,使用一个差的勒芒DI控制器,有一个辅助类注入其中。 我的MVC模型继承自接口以允许它们通过。
因此,有效的Foo和Bar是数据模型。
在我尝试重新编写它以使用Interfaces之前,这一切都正常工作,因为我完全没有问题。
所以,我的总结问题是:
为什么我会收到此错误,如何解决?
如果你需要更多的信息或澄清什么只是大喊:)
希望你能提供帮助。
除此之外,以下评论是针对上述问题做出的,该问题改变了错误:
您可能需要
Foo:IFoo&lt; T&gt;其中T:IBar
然后使用
富&LT;酒吧及GT;
而不仅仅是Foo
这导致了新的错误:
无法转换为Foo&lt; Bar&gt;到IFoo&lt; IBar&gt;
现在,在回应关于协方差和逆变的评论时,我在研究问题时遇到过这种情况,但我不明白为什么它是相关的。我对“泛型”的了解是有限的,我认为我所做的与接口和DI相关的元素有关。
我很确定有人认为再次编辑它是合适的,但它现在有一些人来阅读它需要知道问题是什么以及解决方案是什么(因为有明显的答案)。
供参考:这是我首次发布问题Original Question on Code Project
的地方答案 0 :(得分:1)
您也可以使用通用类型条件执行此操作,例如,如果您将IHelper
更改为此:
public interface IHelper
{
bool DoSomething<T>(IFoo<T> model, string path) where T : IBar;
}
然后您可以实施它:
public class Helper : IHelper
{
public bool DoSomething<T>(IFoo<T> model, string path) where T : IBar
{
//..Save model to path
return true;
}
}
并致电
someHelperInstance.DoSomething(someInstanceOfFoo, somePath);
不再抛出该错误。这是因为您将通用IFoo<T>
限制为任何IBar
派生类型。您可能希望在MSDN上阅读covariance vs contravariance。