获得具体类型的通用方法的T类型

时间:2017-02-01 17:27:32

标签: c# generics casting boxing

我确定以前曾经问过这个问题,但我似乎无法找到我想要的解决方案,尽管SO / Google搜索很长,所以希望你能回答我的问题

为简洁起见,我们假设我有以下对象:

$(".gallery").load(value +".html", showThem);

现在我的控制器中有以下代码:

public interface ISectionView { }
public class SampleSectionView : ISectionView { }
public interface ISectionService<T> where T : ISectionView { }
public class SampleSectionService : ISectionService<SampleSectionView>

出于此目的,_serviceResolver.Resolve方法如下所示:

ISectionView sectionType = new SampleSectionView(); // *** NOTE THE TYPE
var service = _serviceResolver.Resolve(sectionType);

因此,正如我们上面所看到的,我在控制器中创建了sectionType变量作为ISectionView类型,SampleSectionView实现了该类型。这导致我在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;
    }

这是一个问题,因为我的服务想要转换为以下内容:

return resolvableService.Value as ISectionService<ISectionView>;

我知道我已将SampleSectionView对象传递给此resolve方法,但基于通用V类型参数的转换有点丢失。

那么我怎样才能让演员认识到实际的具体类型,而不是它下面创建的接口类型?

为了记录,我知道我可以做到以下几点:

return resolvableService.Value as ISectionService<SampleSectionView>;

但这是一个问题,因为我需要一个Factory方法来创建ISectionView,所以我知道这是我传入Resolve的类型。是的,我可以看出为什么这是一个问题,那么可以做些什么来克服这个问题呢?如果可能的话,我宁愿有一个switch / case语句来处理转换。

谢谢

答案

感谢所有评论。最后,我所要做的就是将ISectionService接口修改为以下内容:

var sectionType = new SampleSectionView(); 

这就足够了。

2 个答案:

答案 0 :(得分:1)

接口不能以这种方式工作,唯一可以将接口IInterface<IBase>强制转换为IInterface<IDerived>的方法是使用out参数声明接口。

我建议您阅读question中的答案。我相信它会为您提供所需的信息。

答案 1 :(得分:1)

我不确定这是最好的解决方案,但你可以将它包装成带有反射的非泛型方法。

class ServiceResolver
{
    public ISectionService<ISectionView> ResolveNonGeneric(ISectionView sectionViewModel)
    {
        var method = GetType()
                     .GetMethod(nameof(Resolve), BindingFlags.Public | BindingFlags.Instance)
                     .MakeGenericMethod(sectionViewModel.GetType());
        return (ISectionService<ISectionView>) method.Invoke(this, new[] { sectionViewModel });
    }

    public ISectionService<V> Resolve<V>(V sectionViewModel) where V : ISectionView 
    {
        //V is SampleSectionView 
    }
}

从而执行:

ISectionView sectionType = new SampleSectionView();
var service = _serviceResolver.ResolveNonGeneric(sectionType);

将在内部执行Resolve<SampleSectionView>

这需要制作ISectionService<T>协变。