Reputation: 2598
My application has a method that caches a value. I need a second method that check if the generic parameter of type T implements IEnumerable and not implements IList. If the answer is yes, the method should do a .ToList and cast it back to T (See comment in code example).
Can you tell me how I do the .ToList() to return a List casted to back to T? (Is it actually possible?)
Something like this:
public T ToListIfIEnumerable<T>(T value)
{
var needToCovert = TypeImplementsGenericIEnumerableButNotGenericIList(value);
if (!needToCovert)
{
return value;
}
// return value.ToList() <-- How to do that???
}
private bool TypeImplementsGenericIEnumerableButNotGenericIList<T>(T value)
{
var type = value.GetType();
var interfaces = type.GetInterfaces();
var gi = typeof(IEnumerable<>);
var gl = typeof(IList<>);
// It would be better if the next lines did't compare strings!
// Suggestions welcome...
var implementsIEnumerable = interfaces.Any(
i => i.IsGenericType && i.Name == gi.Name && i.Namespace == gi.Namespace);
var implementsIList = interfaces.Any(
i => i.IsGenericType && i.Name == gl.Name && i.Namespace == gl.Namespace);
return implementsIEnumerable && !implementsIList;
}
Backgrond info:
The object that uses the method does something like Lazy. Caching an IEnumerable makes not much sense in examples like: Enumerable.Range(1, 3).Select(i => Guid.NewGuid())
It does gives new Guid's every time you call it. That is why I would like to do a ToList().
Upvotes: 2
Views: 793
Reputation: 1499770
Dynamic typing and overloading could help here, if you don't mind using dynamic
:
object ConvertToListIfNecessary(dynamic input)
{
return MaybeToList(input);
}
private IList<T> MaybeToList<T>(IEnumerable<T> input)
{
return input.ToList();
}
private IList<T> MaybeToList<T>(IList<T> input)
{
return input;
}
private object MaybeToList(object input)
{
// Take whatever action you want if the input *doesn't* implement
// IEnumerable<T>
}
Basically this gets the smarts behind dynamic
to do the grungy reflection work for you. It may not be quite as quick as something that's hand-rolled, but it's likely to be much simpler to get right.
Upvotes: 4