检查通用接口上的约束
Check constraint on generic interface
我的界面如下:
public interface IHasDetailPage<TViewModel> where TViewModel : ViewModelBase
{
TViewModel GetViewModel();
}
稍后在我的代码中,我有一个我知道实现此接口的对象。但是,在编译时,我确实知道它使用的特定类型参数。我想通过调用上面的函数来检索该对象的 ViewModel:
ModelBase Target = DbHelper.Find(... // Retrieves this object from the database
if(Target is IHasDetailPage<ViewModelBase>)
{
ViewModel = (Target as IHasDetailPage<ViewModelBase>).GetViewModel();
}
同样,我知道 Target
实现了 IHasDetailPage
,并且 ViewModel 是 ViewModelBase
的子类。但是这个 if 语句失败了,如果我删除它,转换就会失败 (returns null
)。我假设是因为 Target 没有具体实现 IHasDetailPage<ViewModelBase>
,但是 IHasDetailPage<SpecificViewModel>
,甚至很难实现 SpecificViewModel : ViewModelBase
。
如何执行此类型检查并正确转换?真的,我只需要能够调用 GetViewModel()
,但我想了解如何正确完成此操作,以及为什么我的方法不起作用。
如果您可以控制接口,则可以使其协变。以下测试通过...
[TestMethod]
public void DetailPage_ShouldBeOfFooType()
{
var target = new Target();
Assert.IsTrue(target is IHasDetailPage<Foo>);
}
public class Foo { }
public class Bar : Foo { }
public interface IHasDetailPage<out TViewModel> where TViewModel : Foo
{
TViewModel GetViewModel();
}
public class Target : IHasDetailPage<Bar>
{
public Bar GetViewModel() { return null; }
}
我的界面如下:
public interface IHasDetailPage<TViewModel> where TViewModel : ViewModelBase
{
TViewModel GetViewModel();
}
稍后在我的代码中,我有一个我知道实现此接口的对象。但是,在编译时,我确实知道它使用的特定类型参数。我想通过调用上面的函数来检索该对象的 ViewModel:
ModelBase Target = DbHelper.Find(... // Retrieves this object from the database
if(Target is IHasDetailPage<ViewModelBase>)
{
ViewModel = (Target as IHasDetailPage<ViewModelBase>).GetViewModel();
}
同样,我知道 Target
实现了 IHasDetailPage
,并且 ViewModel 是 ViewModelBase
的子类。但是这个 if 语句失败了,如果我删除它,转换就会失败 (returns null
)。我假设是因为 Target 没有具体实现 IHasDetailPage<ViewModelBase>
,但是 IHasDetailPage<SpecificViewModel>
,甚至很难实现 SpecificViewModel : ViewModelBase
。
如何执行此类型检查并正确转换?真的,我只需要能够调用 GetViewModel()
,但我想了解如何正确完成此操作,以及为什么我的方法不起作用。
如果您可以控制接口,则可以使其协变。以下测试通过...
[TestMethod]
public void DetailPage_ShouldBeOfFooType()
{
var target = new Target();
Assert.IsTrue(target is IHasDetailPage<Foo>);
}
public class Foo { }
public class Bar : Foo { }
public interface IHasDetailPage<out TViewModel> where TViewModel : Foo
{
TViewModel GetViewModel();
}
public class Target : IHasDetailPage<Bar>
{
public Bar GetViewModel() { return null; }
}