接口扩展方法在实现类上不可见

时间:2016-10-01 03:28:37

标签: c# interface extension-methods visibility

我已经定义了一个“类型转换器”界面(请不要提及AutoMapper,不相关),如下所示:

public interface ITranslator<TSource, TResult>
{
    TResult Translate(TSource source);
}

为了方便起见,我已经为枚举定义了一个扩展方法:

public static class ExtendITranslator
{
    public static IEnumerable<TResult> TranslateSet<TSource, TResult>(
        this ITranslator<TSource, TResult> self, 
        IEnumerable<TSource> sourceSet)
    {
        return sourceSet.Select(o => self.Translate(o));
    }
}

然后我将实现定义为:

public class Translator :
    ITranslator<Report, Report.ReportServiceModel>,
    ITranslator<Report.ReportServiceModel, Report>
{
    public Report Translate(Report.ReportServiceModel source)
    {
        throw new NotImplementedException();
    }

    public Report.ReportServiceModel Translate(Report source)
    {
        throw new NotImplementedException();
    }
}

问题是,当我使用Translator实现时,它不会将TranslateSet公开为扩展方法,除非我强制转换:

Translator translator = new Translator();

// not exposed
translator.TranslateSet(/* ... */);

// exposed with a cast
(translator as ITranslator<Report, Report.ReportServiceModel>).TranslateSet(/* ... */);

为什么会这样?其他类实现公开为它们实现的接口定义的扩展方法:

public interface IUpdater<TModel> where TModel : class, new()
{
    bool Update(TModel model);
}

public static class ExtendIRepositoryWriter
{
    public static int UpdateSet<TModel>(
        this IRepositoryWriter<TModel> self,
        IEnumerable<TModel> modelSet) where TModel : class, new()
    {
        return modelSet.Count(o => self.Update(o));
    }
}

public class ReportUpdater : IUpdater<Report>
{
    public bool Update(Report model)
    {
        throw new NotImplementedException();
    }
}

在这种情况下,UpdateSet的实例可以使用ReportUpdater扩展方法:

ReportUpdater reportUpdater = new ReportUpdater();

// all good!
reportUpdater.UpdateSet(/* ... */);

有人可以对此有所了解吗?我是不是指责一个错字? (毕竟是星期五晚上)

1 个答案:

答案 0 :(得分:1)

你的另一个工作实例实际上是误导性的,并不是真正的苹果对比。

由于单个泛型参数,编译器能够推断出类型,因为您正在调用该类型的实例。

由于存在两个类型参数,因此扩展不会给您带来麻烦。您可以通过将具体类型分配给声明类型的接口来解决此问题。

ITranslator<Report, Report.ReportServiceModel> translator = new Translator();

translator.TranslateSet(/* ... */);