我有一个从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属性...
可以这样做吗?我在搜索提到协方差的时候已经看到了,但我似乎无法理解它,这是我需要做的工作吗?
我也看到使用反射作为解决方案,但这很昂贵,并且不适用于我的特定情况。
最后我看到,如果我将基础定义为接口而不是抽象类,这可以工作,但我需要基本行为,因为它将在所有继承类型中共享...
我输入这个问题的主要原因是因为总是提出类似的问题,我通常最终找到了答案,但这次我真的迷失了协方差和泛型,所以我可以使用一些洞察力来确定这是否可能,或者我是否应该以完全不同的方式这样做...
答案 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())...