Given the following code (which I know won't compile and isn't correct):
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
}
And this example setup:
var myFetchers = new List<Fetcher> {
new Fetcher<string>(() => new List<string> { "white", "black" })),
new Fetcher<int>(() => new List<int> { 1, 2 }))
};
How can I structure my code so that this will work?
IEnumerable<IEnumerable<object>> fetcherResults =
myFetchers.Select(fetcher => fetcher.Fetch()); // get objects from derived method
TLDR; I've thought about this a little more. A different way to state my question is: how do I run the Fetch
method on all the items in the myFetchers
list and save a collection of their results, without having to determine the base type of each item and do a cast to that type, while not returning IEnumerable<object>
from the Fetch
method itself?
The key here is that at the time the objects of different generic type are in a collection of the parent type, I want to run the derived type's method, but return the result as IEnumerable<object>
, not IEnumerable<T>
. (This can be done using a different method if necessary, I suppose, though it would be nice if it were the same name.) This is so that a section of the code that doesn't need to know about fetchers can have its data (and just be passed fetcherResults
), but the part of the code that does care about fetchers can completely ignore what type of data the fetchers work with (not its concern, only the consumer of the data needs to work with the specific types).
I don't have to use inheritance here, and interface IFetcher
would work just as well. I keep thinking about how explicit interface implementation might help, but I'm just not closing the loop right now how to make this work for me:
// in a class implementing ICollection<T>
public IEnumerator<T> GetEnumerator() => _collection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) _collection).GetEnumerator();
As usual, the real situation is more complicated than this (such as the data the fetchers are providing coming from a database, etc.). But getting this one part down will be all I need.
I have looked at the following resources to no avail: implement an inheritable method that returns an object, call method on generic type from abstract parent.
There is a straight-forward way to do this with explicit implementation as you suspected. This is only available if you use an interface rather than an abstract class.
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();
}
In this implementation, the interface version of the call returns IEnumerable<object>
, while the class-accessible version returns the more specific IEnumerable<T>
. If you call the fetcher through the interface, it will resolve to the first. Calling through the class will resolve to the second.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With