I am writing a little serialization library in .net. The goal is to have a replacement for XmlSerialize but easier to configure and without messing up the model with attributes.
The problem that I face is that I need the type of each ICollection<T> I find during traversing the model.
The naive approach is this:
var theType=myModel.GetType().GetGenericArguments()[0];
But it does not help for classes that derive from ICollection<T> with a specific T.
public class MyClass:A,ICollection<B>{}
I tried getting the interface with reflection
var iCollectionInterface =
o.GetType().GetInterfaces()
.Where(i => i.IsGenericType)
.Select(i => i.GetGenericTypeDefinition())
.FirstOrDefault(i => i == typeof(ICollection<>));
but iCollectionInterface.GetGenericArguments()[0] is just T, not B because it describes only the definition of the interface and not the usage of it.
Any ideas? I also need it for IDictionary<TKey, TValue> but that is basically the same problem and will have the same solution.
Thank you!
Edit
Thank you all, here is what I ended up with:
public static Type GetTypeParameter(object o, Type typeToSearch, int argumentNumber)
{
return o.GetType()
.GetInterfaces()
.Where(i => i.IsGenericType)
.Where(i => i.GetGenericTypeDefinition() == typeToSearch)
.Select(t => t.GetGenericArguments()[argumentNumber])
.FirstOrDefault();
}
From the comments it seems you need to figure out how to filter the collection to only include ICollection. You can reach that goal by:
var iCollectionInterfaces =
from i in o.GetType().GetInterfaces()
where i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IColection<>)
select i;
You can then iterate over the collection and do whatever you need to with each type argument
//same type might implement ICollection<T> more than once
foreach(var collection in iCollectionInterfaces) {
//More than one is invalid for ICollection<T>
var T = collection.GetGenericArguments().Single();
//do what ever you need
}
of course if you want to make it more generic. Ie to support interfaces/types with more than one type argument you need to remove the call to Single and replace with iteration of the type arguments
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