【问题标题】:InvalidCastException when casting an entity to a interface for use within a static method将实体转换为接口以在静态方法中使用时出现 InvalidCastException
【发布时间】:2012-01-07 03:20:34
【问题描述】:

我在将实体转换为要在静态方法中使用的接口时遇到问题。我得到的错误是 InvalidCastException。我需要执行此转换,因为我有一个需要采用特定接口定义的静态方法。我认为(尽管我没有尝试过)使用抽象类而不是接口可能会起作用,但是 C# 不支持从抽象类继承,并且我的实体已经从一个抽象类继承。

我的模型相当简单。我有一个实体对象 - MemberStatus - 它有一个 Id、Name 和 DisplayOrder。它继承自 Entity 抽象类(继承自 IIdentifiableEntity)并实现 INamedEntity、IOrderedEntity 接口。这些抽象类或接口中的每一个都只包含一个属性(Id、Name 和 DisplayOrder)。

这是我的域项目中的代码:

public abstract class Entity : IIdentifiableEntity
{
  public int Id { get; set; }
}

public interface INamedEntity
{
  string Name { get; set; } 
}

public interface IOrderedEntity
{
  float DisplayOrder { get; set; }
}

public class MemberStatus : Entity, INamedEntity, IOrderedEntity
{
  public string Name { get; set; }
  public float DisplayOrder { get; set; }
}

public interface IRepository<TEntity>
{
  TEntity FindById(int id);
  bool InsertOrUpdate(TEntity entity);
  //... More methods here
}

这是我的静态方法(我希望能够用于任何 IOrderedEntity):

public static void MoveDisplayOrder(IRepository<IOrderedEntity> repository, int id, bool moveUp)
{
  var currentStatus = repository.FindById(id);
  //...do reordering work
  repository.InsertOrUpdate(currentStatus);
}

在我的 MVC 控制器中(在我的 Web 项目中),我有以下内容:

public class AdminController : Controller
{
  private readonly IRepository<MemberStatus> _memberStatusRepository;

  public AdminController(IRepository<MemberStatus> memberStatusRepository)
  {
    _memberStatusRepository = memberStatusRepository;
  }

  public ActionResult StatusMoveDisplayOrder(int id, bool moveUp)
  {
    // Code fails on the following line...
    MoveDisplayOrder((IRepository<IOrderedEntity>) _memberStatusRepository, id, moveUp);
    return RedirectToAction("Index");
  }

  // Rest of controller code here...
}

当控制器调用 StatusMoveDisplayOrder 并反过来尝试调用静态 MoveDisplayOrder 时,代码会失败(在运行时...它可以正常编译)。在我将 MoveDisplayOrder 设为静态并将第一个参数从 IRepository&lt;MemberStatus&gt; 更改为 IRepository&lt;IOrderedEntity&gt; 之前,所有这些代码都运行良好。同样,我进行了更改,以便可以在任何具有 DisplayOrder 属性的实体上调用此方法(实现 IOrderedEntity)。我做错了什么?

仅供参考 - 我正在使用 ninject,以防我需要调整其中的内容。

【问题讨论】:

  • “C# 不支持从抽象类继承”?不太清楚你的意思,也许你的意思是 C# 不支持 multiple 继承?它肯定支持从抽象类继承。
  • 这就是我的意思,如果我没有说清楚的话。

标签: c# c#-4.0 interface static-methods .net


【解决方案1】:

IRepository&lt;MemberStatus> 不是 IRepository&lt;IOrderedEntity&gt;,即使 MemberStatus 实现了 IOrderedEntity。如果您真的希望能够进行类型转换,则需要使 IRepository 成为像这样的协变通用接口。

interface IRepository<out T>
{
}

http://msdn.microsoft.com/en-us/library/dd997386.aspx

这是不可能的,因为 IRepository 的方法不能将 TEntity 作为参数。您可以更改静态方法,而不是强制转换..

public static void MoveDisplayOrder<T>(IRepository<T> repository, int id, 
    bool moveUp) where T : IOrderedEntity
{
  var currentStatus = repository.FindById(id);
  //...do reordering work
  repository.InsertOrUpdate(currentStatus);
}

【讨论】:

  • 谢谢,但我刚刚尝试过,它在我的代码中导致了大量的编译错误。我的存储库类有一堆现有的方法,表明它们必须更新以允许变化。是否有另一种方法对更改不那么具有侵入性?也许通过强制转换到某种列表来消除直接访问存储库的需要?
  • 我之前太着急了,没有处理你的整个问题,只处理了这个错误。对于那个很抱歉。如果您将静态方法设为通用,则根本不需要强制转换,请参阅我的更新。
  • 完美!那解决了它。我应该意识到这一点,因为这与我的具体存储库所做的事情是一样的。感谢您的帮助!
猜你喜欢
  • 2021-02-10
  • 2014-08-06
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 2015-05-27
  • 2020-10-13
  • 1970-01-01
相关资源
最近更新 更多