鉴于以下代码(我知道它不会编译并且不正确):
public abstract class Fetcher {
public abstract IEnumerable<object> Fetch();
}
public class Fetcher<T> : Fetcher {
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
public IEnumerable<T> Fetch() => _fetcher(); // override or new
}
这个示例设置:
var myFetchers = new List<Fetcher> {
new Fetcher<string>(() => new List<string> { "white", "black" })),
new Fetcher<int>(() => new List<int> { 1, 2 }))
};
如何构建我的代码以便这可以工作?
IEnumerable<IEnumerable<object>> fetcherResults =
myFetchers.Select(fetcher => fetcher.Fetch()); // get objects from derived method
TLDR; 我已经考虑过这个了。陈述我的问题的另一种方式是:如何对Fetch
列表中的所有项目运行myFetchers
方法并保存其结果集合,而无需确定每个项目的基本类型并对该类型进行强制转换,而不是从IEnumerable<object>
方法本身返回Fetch
?
这里的关键是,当不同泛型类型的对象在父类型的集合中时,我想运行派生类型的方法,但返回结果为IEnumerable<object>
,而不是{{1 }}。 (如果需要的话,这可以使用不同的方法来完成,但是如果它是相同的名称会很好。)这样,不需要了解取件器的代码部分可以拥有其数据(并且只是传递IEnumerable<T>
),但是关注提取器的代码部分可以完全忽略提取器使用的数据类型(不关心它,只有数据的使用者需要使用特定类型)。
我不必在这里使用继承,接口fetcherResults
也可以正常工作。我一直在思考显式接口实现可能有多大帮助,但我现在还没有关闭循环如何使这个工作对我有用:
IFetcher
像往常一样,真实情况比这更复杂(例如提取者提供的数据来自数据库等)。但是把这一部分放下来将是我所需要的全部。
我查看了以下资源但无济于事:implement an inheritable method that returns an object,call method on generic type from abstract parent。
答案 0 :(得分:3)
有一种直接的方法可以通过您怀疑的显式实现来完成此操作。这仅在您使用接口而不是抽象类时才可用。
public interface IFetcher {
IEnumerable<object> Fetch();
}
public class Fetcher<T> : IFetcher {
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
IEnumerable<object> IFetcher.Fetch() => Fetch().Cast<object>();
public IEnumerable<T> Fetch() => _fetcher();
}
在此实现中,调用的接口版本返回IEnumerable<object>
,而类可访问版本返回更具体的IEnumerable<T>
。如果通过界面调用fetcher,它将解析为第一个。通过课程调用将解决到第二个。
答案 1 :(得分:2)
如果我正确理解了这个问题,那么您可以通过Fetcher<T>
实现这样的通用接口IFetcher<T>
来解决问题:
public interface IFetcher<T>
{
IEnumerable<T> Fetch();
}
public class Fetcher<T> : IFetcher<T>
{
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
public IEnumerable<T> Fetch() => _fetcher();
}
然后创建一个可以将IFetcher<TFrom>
转换为IFetcher<TTo>
的适配器,如下所示:
public class Adaptor<TFrom, TTo> : IFetcher<TTo>
{
private readonly IFetcher<TFrom> _fetcher;
public Adaptor(IFetcher<TFrom> fetcher)
{
_fetcher = fetcher;
}
public IEnumerable<TTo> Fetch()
{
return _fetcher.Fetch().Cast<TTo>();
}
}
例如,这允许从IFetcher<string>
转换为IFetcher<object>
。
借助此扩展方法:
public static class ExtensionMethods
{
public static Converter<TFrom> Convert<TFrom>(this IFetcher<TFrom> fetcher)
{
return new Converter<TFrom>(fetcher);
}
public class Converter<TFrom>
{
private readonly IFetcher<TFrom> _fetcher;
public Converter(IFetcher<TFrom> fetcher)
{
_fetcher = fetcher;
}
public IFetcher<TTo> To<TTo>()
{
return new Adaptor<TFrom, TTo>(_fetcher);
}
}
}
你可以轻松地做这样的事情:
static void Main(string[] args)
{
var myFetchers = new List<IFetcher<object>>
{
new Fetcher<string>(() => new List<string> { "white", "black" }).Convert().To<object>(),
new Fetcher<int>(() => new List<int> { 1, 2 }).Convert().To<object>()
};
var results = myFetchers.Select(x => x.Fetch());
}
请注意,您可以不使用扩展方法,但它会使您的代码更具可读性。