【发布时间】:2017-02-01 17:27:31
【问题描述】:
我确定以前有人问过这个问题,但我似乎无法找到我正在寻找的解决方案,尽管 SO/Google 搜索了很长时间,所以希望你能回答我的问题。
为简洁起见,假设我有以下对象:
public interface ISectionView { }
public class SampleSectionView : ISectionView { }
public interface ISectionService<T> where T : ISectionView { }
public class SampleSectionService : ISectionService<SampleSectionView>
现在我的控制器中有以下代码:
ISectionView sectionType = new SampleSectionView(); // *** NOTE THE TYPE
var service = _serviceResolver.Resolve(sectionType);
为此,_serviceResolver.Resolve 方法如下所示:
public ISectionService<V> Resolve<V>(V sectionViewModel)
where V : ISectionView
{
var sectionViewModelTypeName = sectionViewModel.GetType().Name;
// Ignore this, it's some AutoFac metadata resolution
var resolvableService = _services.FirstOrDefault(s => s.Matches(sectionViewModelTypeName));
if (resolvableService != null)
return resolvableService.Value as ISectionService<V>; // Upcast, as this is the actual type we want!
return null;
}
所以,正如我们在上面看到的,我在控制器中创建了 sectionType 变量作为 ISectionView 类型,SampleSectionView 实现了它。这导致我在 resolve 方法中出现问题,因为它实际上在做什么(正如我在即时窗口中检查过的那样)如下:
return resolvableService.Value as ISectionService<ISectionView>;
这是一个问题,因为我的服务想要转换为以下内容:
return resolvableService.Value as ISectionService<SampleSectionView>;
我知道我已将 SampleSectionView 对象传递给此解析方法,但基于泛型 V 类型参数的转换有点丢失。
那么我怎样才能让演员识别实际的具体类型,而不是创建它的接口类型呢?
郑重声明,我知道我可以做到以下几点:
var sectionType = new SampleSectionView();
但这是一个问题,因为我需要一个工厂方法来创建 ISectionView,所以我知道这是我传递给 Resolve 的类型。是的,我明白为什么这是一个问题,那么可以做些什么来克服这个问题呢?如果可能的话,我宁愿不有一个 switch/case 语句来处理转换。
谢谢
回答
感谢所有评论。最后,我所要做的就是将 ISectionService 接口修改为以下内容:
public interface ISectionService<out T> where T : ISectionView { }
这就够了。
【问题讨论】:
-
你能以某种方式拥有一个非泛型接口而不是泛型接口吗?我认为您拥有
as是否正确,因为没有它它会抱怨返回类型不正确? -
您需要调用
.Resolve<SampleSectionView>(...),因为编译器在查看解析调用时“知道”的唯一类型是变量的类型,它是一个接口。它不使用底层类型的类型,我理解是你想要的。 -
克里斯,是的,resolvableService.Value 返回一个 IResolvableService。每个 ISectionService 也实现了这个接口,正是这个 IResolvableService 用于 AutoFac 目的。这就是为什么我现在需要将它与我想要的界面相协调。
标签: c# generics casting boxing