转换为抽象通用基类

时间:2014-01-28 02:32:46

标签: c# generics casting abstract-class

我有一个从Mvc继承的抽象泛型类 Controller 使用泛型类型来创建项目字典,类似于:

public abstract class BaseController<TElement> : Controller where TElement : BaseElement
{
    public Dictionary<string, TElement> Stuff { get; set; }
    string Name;

    public BaseController()
    {
        this.Name = Helper.GetName();
        this.Stuff = Helper.GetStuff(Name) as Dictionary<string, TElement>;
    }
}

然后我有几个不同的BaseControllers实现,它们传递不同类型的BaseElement,基于命名对象的标准(我相信这部分是无关紧要的,但请告诉我它是否影响我的最终结果)。

问题是稍后我需要检查动作过滤器中的“Stuff”属性是否为null,动作过滤器通过基本Mvc Controller属性访问BaseController的实例。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = filterContext.Controller as **BaseWidgetController**; // <-- here
    if (controller == null)
        throw new Exception(filterContext.Controller.GetType().ToString());
}

我的“BaseController”是一个控制器,所以它确实适合该属性,但我无法弄清楚如何将它转换为我的BaseController类型以获取Stuff属性...

可以这样做吗?我在搜索提到协方差的时候已经看到了,但我似乎无法理解它,这是我需要做的工作吗?

我也看到使用反射作为解决方案,但这很昂贵,并且不适用于我的特定情况。

最后我看到,如果我将基础定义为接口而不是抽象类,这可以工作,但我需要基本行为,因为它将在所有继承类型中共享...

我输入这个问题的主要原因是因为总是提出类似的问题,我通常最终找到了答案,但这次我真的迷失了协方差和泛型,所以我可以使用一些洞察力来确定这是否可能,或者我是否应该以完全不同的方式这样做...

1 个答案:

答案 0 :(得分:3)

很难编写从基类到通用派生类之一的强类型代码。一种选择是使用dynamic而不是强类型代码。

另一个选择是拥有非通用基类或接口,除非您需要使用特定类型的元素:

interface IHasTheStuff
{
  bool HaveStuff();
}

public abstract class BaseController<TElement> : IHasTheStuff, Controller ...
{
   ...
   public bool HaveStuff() { return Stuff != null;}
}

而且当你只有控制器转换到该界面时:

Controller justController...
if (((IHasTheStuff)justController).HaveStuff())...