I have some classes implementing an interface:
class FirstImplementer : IInterface { ... }
class AnotherImplementer : IInterface { ... }
Somewhere in the code, I got a list of instances of IInterface.
List<IInterface> MyList;
I want to know for each IInterface instance what is the implementer class of that specific instance (FirstImplementer or AnotherImplementer).
You can just use .GetType() on the instances in MyList and go from there.
MyList[0].GetType() > This is the same as typeof(FirstImplementer) et al.
foreach (var item in MyList)
{
var theType = item.GetType();
// why did you want theType, again?
// you generally shouldn't be concerned with how your interface is implemented
}
This alternative may be more useful, depending on what you're trying to do:
foreach (var item in MyList)
{
if (item is FirstImplementer)
{
var firstImpl = (FirstImplementer)item;
// do something with firstImpl
}
else if (item is AnotherImplementer)
{
var anotherImpl = (AnotherImplementer)item;
// do something with anotherImpl
}
}
It's generally better to use is or as over reflection (e.g. GetType) when it might make sense to do so.
foreach (var instance in MyList)
{
Type implementation = instance.GetType ();
}
If you need to get the first type argument if any, and null if no such type argument even exists for each instance in your list, which at design time you syntactically observe as interface references then you could use the GetGenericArguments method of the Type type.
Here's a little helper method which takes a bunch of objects
which may be null, but which would surely implement your interface if they weren't
(they would have a runtime type that did) and yields a bunch of types which
represent (in respective order) the discovered type arguments in a SomeImplementer pattern:
public IEnumerable<Type> GetTypeArgumentsFrom(IEnumerable<IInterface> objects) {
foreach (var obj in objects) {
if (null == obj) {
yield return null; // just a convention
// you return null if the object was null
continue;
}
var type = obj.GetType();
if (!type.IsGenericType) {
yield return null;
continue;
}
yield return type.GetGenericArguments()[0];
}
}
Related
I'm trying to make a model reflection tool. I have come a long way so far but now i'm stuck.
I have this
public static void RenderModelList(List<T> modelList)
{
foreach (T model in modelList)
{
PropertyInfo[] properties = model.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(model, null);
//Check if the property is a collection and do recursion
if (propValue != null)
{
if (isCollection(propValue))
{
//This only works for Lists of the same <T>
List<T> li = Convert.ChangeType(propValue, propValue.GetType()) as List<T>;
if (li != null)
{
if (li.Count > 0)
{
RenderModelList(li, loop);
}
}
else
{
//Its another type what to do?
// Create a List<> of unknown type??
}
}
}
}
}
}
My problem is that if I pass this method a List<Persons> and the Person has a property which is a List<Cars> - I can't use Convert.ChangeType - because this is not the T.
So how do I loop thrugh a "List" and get access to the properties of this object ?
It seems to me that your method can be a lot more loosely typed:
public static void RenderModelList(IEnumerable list)
{
foreach (object model in list)
{
...
}
}
Then you just need to cast to IEnumerable, not a specific sequence or list type.
Well, your method should not rely on T. You can just use IEnumerable instead (not IEnumerable<T>, because it again depends on T). Note that every List<T> implements IEnumerable, so your method will work with them; however, other collections often implement IEnumerable as well. This may or may not be what you need.
If you choose the proposed way, your test isCollection will be like this:
IEnumerable propValueAsEnumerable = propValue as IEnumerable;
if (propValueAsEnumerable != null)
RenderModelList(propValueAsEnumerable);
I would perhaps refactor your method into something like that:
IEnumerable<object> GetPropertyValuesFlat(object o)
{
return o.GetType()
.GetProperties()
.Select(pi => pi.GetValue(o, null))
.Where(pv => pv != null)
.SelectMany(pv => pv is IEnumerable<object> ?
(IEnumerable<object>)pv : new[] {pv});
}
//...
foreach (object p in GetPropertyValuesFlat(o))
render(p);
(caution: not tested)
Edit: well, won't work as SelectMany doesn't understand non-generic IEnumerable. Changed it to work with IEnumerable<object>. At least, each IEnumerable<T> is an IEnumerable<object> with class T.
This is a bit difficult to explain. So here it goes.
I have a function like this:
public T FooBar<T>(Func<T> function)
{
T returnData = function();
// want to iterate through returnData to do something to it
return returnData;
}
If the returnData (T) is an IEnumerable list, then I would like to enumerate through returnData to modify its contents using reflection. But I can't seem to be able to do it. When I try to cast returnData to an enumerable type, I get an exception:
Unable to cast object of type
'System.Collections.Generic.List`1[Cars]'
to type
'System.Collections.Generic.List`1[System.Object]'.
I will not know that the return type will be a list of 'cars' for example ahead of time, only at run time. So I have to check using reflection if it is a list, and then try to cast it so that I can enumerate through it.
Unless I am going about it the wrong way. How can I enumerate through returnData if it is of type T?
One approach is to add a type constraint on T, but this is not ideal:
public T FooBar<T>(Func<T> function) where T : IEnumerable
{
// T is not strongly typed for the enumerated item
If you changed your method slightly (w.r.t. T):
public IEnumerable<T> FooBar<T>(Func<IEnumerable<T>> function)
Then you have strong typing on the actual item being enumerated with the added bonus of accepting enumerable objects.
So I noticed from a second read of your question, there is some confusion about what T means for your variable returnData. In the case where FooBar() is passed a List<Car>, T is List<Car>, and really has no association with the generic type specification of the List<> itself. You can think of it as some List<U> where U is some other, unknown type.
At runtime you will have no simple way to get to U as it is hidden, so to speak, inside T. You could use overloading as some of the other answerers recommend, and provide a non-IEnumerable<U> method and one which takes arguments of type Func<IEnumerable<T>>.
Perhaps with some more details about the goal of FooBar<T> we could make some more specific recommendations.
if (returnData is System.Collections.IEnumerable)
{
foreach (object o in (System.Collections.IEnumerable)returnData)
{
// Do something.
}
}
Really, though, why not have an additional overload like this:
public T FooBar<T>(Func<IEnumerable<T>> function)
Have you tried type casting to IEnumerable instead of IEnumerable<T>? With IEnumerable you can still use it in a foreach loop. The variable each item would go in should be of type object i.e.:
foreach(object item in (IEnumerable)T){...}
You should check first to be sure that T implements IEnumerable.
The issue here is IEnumerable and IEnumerable Of T are not the same... but you can check for the difference and account for it in your code. Note that IEnumerable Of T inherits IEnumerable, so you can wrap the check for the generic version inside the non-generic version.
The following worked for me in a small test I wrote - I hope it is sufficient for you to do what you need.
Here is the meat and potatoes:
class FooBarOfT
{
public T FooBar<T>(Func<T> function)
{
T returnData = function();
//Want to iterate through returnData to do something to it.
if (returnData is IEnumerable)
{
// get generic type argument
var returnDataType = returnData.GetType();
if (returnDataType.IsGenericType)
{
// this is a System.Collections.Generic.IEnumerable<T> -- get the generic type argument to loop through it
Type genericArgument = returnDataType.GetGenericArguments()[0];
var genericEnumerator =
typeof(System.Collections.Generic.IEnumerable<>)
.MakeGenericType(genericArgument)
.GetMethod("GetEnumerator")
.Invoke(returnData, null);
IEnumerator enm = genericEnumerator as IEnumerator;
while (enm.MoveNext())
{
var item = enm.Current;
Console.WriteLine(string.Format("Type : {0}", item.GetType().Name));
}
}
else
{
// this is an System.Collections.IEnumerable (not generic)
foreach (var obj in (returnData as IEnumerable))
{
// do something with your object
}
}
}
return returnData;
}
}
I also set up some supporting test classes:
class Foo
{
private string _fooText;
public Foo(string fooText)
{
_fooText = fooText;
}
public string Execute()
{
return string.Format("executed! with {0} !", _fooText);
}
}
class Bar
{
public string BarContent { get; set; }
}
And a small console app to run some tests:
class Program
{
static void Main(string[] args)
{
// tests
Func<string> stringFunc = () =>
"hello!";
Func<List<Foo>> listFooFunc = () =>
new List<Foo>
{
new Foo("Hello!"),
new Foo("World!")
};
Func<IEnumerable> ienumerableFooFunc = () =>
new Hashtable
{
{ "ItemOne", "Foo" },
{ "ItemTwo", "Bar" }
};
var fooBarOfT = new FooBarOfT();
fooBarOfT.FooBar(stringFunc);
fooBarOfT.FooBar(listFooFunc);
fooBarOfT.FooBar(ienumerableFooFunc);
Console.ReadKey();
}
}
In some part of my code I am passed a collection of objects of type T. I don't know which concrete colletion I will be passed, other than it impements IEnumerable.
At run time, I need to find out which type T is (e.g. System.Double, System.String, etc...).
Is there any way to find it out?
UPDATE: I should maybe clarify a bit more the context I am working in (a Linq Provider).
My function has a signature like the following, where I get the type of the collection as a parameter:
string GetSymbolForType(Type collectionType)
{
}
Is there any way from collectionType to get the contained objects type?
From Matt Warren's Blog:
internal static class TypeSystem {
internal static Type GetElementType(Type seqType) {
Type ienum = FindIEnumerable(seqType);
if (ienum == null) return seqType;
return ienum.GetGenericArguments()[0];
}
private static Type FindIEnumerable(Type seqType) {
if (seqType == null || seqType == typeof(string))
return null;
if (seqType.IsArray)
return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
if (seqType.IsGenericType) {
foreach (Type arg in seqType.GetGenericArguments()) {
Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
if (ienum.IsAssignableFrom(seqType)) {
return ienum;
}
}
}
Type[] ifaces = seqType.GetInterfaces();
if (ifaces != null && ifaces.Length > 0) {
foreach (Type iface in ifaces) {
Type ienum = FindIEnumerable(iface);
if (ienum != null) return ienum;
}
}
if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
return FindIEnumerable(seqType.BaseType);
}
return null;
}
}
myCollection.GetType().GetGenericArguments()
will return an array of the type args.
Type t = null
foreach(object o in list)
{
o.GetType();
}
will get you the type of the object.
Then you should probably test for your desired types:
if(t == typeof(myClass))
{
dosomething();
}
else if (t == typeof(myOtherClass))
{
dosomethingelse();
}
I use dynamic alot and this is an issue from time to time.
Matt Davis nailed it but you need the index :)
public static void PopulateChildCollection<T>(T currentObject, string singlePropertyName)
{
dynamic currentObjectCollection = ReflectionTools.GetPropertyValue(currentObject, singlePropertyName);
Type collectionType = currentObjectCollection.GetType().GetGenericArguments()[0];
The type will be what you would expect, it is the type of the object contained in the collection and not any of the generic types surrounding it.
Cant you just use t.GetType() to do this.
Why not just implement an IEnumerable<T> instead? EG:
public void MyFunc<T>(IEnumerable<T> objects)
Other than that, you'd be better off checking the type of each individual object using is or .GetType rather than trying to work it out from the container itself.
If that's not an option though and you really need to know the type of the base container you'd basically have to check using is to see what interfaces it implements (EG: IList<int> etc). Odds are the type of your array is going to be a generic which means trying to work back from it's name down to it's data type will be quite messy.
Well I am way way late here but shouldn't this work :
public static bool ThatCollectionIsOfType<T>(IEnumerable<T> collection, Type got)
{
if (**typeof(T)** == got) //this line should be good to go...
{
return true;
}
}
I'm working on a game engine in C#. The class I'm working on is called CEntityRegistry, and its job is to keep track of the many instances of CEntity in the game. My goal is to be able to query the CEntityRegistry with a given type, and get a list of each CEntity of that type.
What I'd like to do, therefore, is maintain a map:
private IDictionary<Type, HashSet<CEntity>> m_TypeToEntitySet;
And update the registry thusly:
private void m_UpdateEntityList()
{
foreach (CEntity theEntity in m_EntitiesToRemove.dequeueAll())
{
foreach (HashSet<CEntity> set in m_TypeToEntitySet.Values)
{
if (set.Contains(theEntity))
set.Remove(theEntity);
}
}
foreach (CEntity theEntity in m_EntitiesToAdd.dequeueAll())
{
Type entityType = theEntity.GetType();
foreach (Type baseClass in entityType.GetAllBaseClassesAndInterfaces())
m_TypeToEntitySet[baseClass].Add(theEntity);
}
}
The problem I have is that there is no function Type.GetAllBaseClassesAndInterfaces- How would I go about writing it?
You could write an extension method like this:
public static IEnumerable<Type> GetBaseTypes(this Type type) {
if(type.BaseType == null) return type.GetInterfaces();
return Enumerable.Repeat(type.BaseType, 1)
.Concat(type.GetInterfaces())
.Concat(type.GetInterfaces().SelectMany<Type, Type>(GetBaseTypes))
.Concat(type.BaseType.GetBaseTypes());
}
More refined answer based on one from SLaks would be:
public static IEnumerable<Type> GetBaseClassesAndInterfaces(this Type type)
{
return type.BaseType == typeof(object)
? type.GetInterfaces()
: Enumerable
.Repeat(type.BaseType, 1)
.Concat(type.GetInterfaces())
.Concat(type.BaseType.GetBaseClassesAndInterfaces())
.Distinct();
}
Type has a property BaseType and a method FindInterfaces.
https://msdn.microsoft.com/en-us/library/system.type.aspx
So actually, it almost does have Type.GetAllBaseClassesAndInterfaces, but you have to make two calls instead of one.
Here. The previous answers have problems.
Also, this answer doesn't need "Distinct". The values are already distinct. And this one is more efficient.
public static IEnumerable<Type> GetBaseTypes(this Type type, bool bIncludeInterfaces = false)
{
if (type == null)
yield break;
for (var nextType = type.BaseType; nextType != null; nextType = nextType.BaseType)
yield return nextType;
if (!bIncludeInterfaces)
yield break;
foreach (var i in type.GetInterfaces())
yield return i;
}
Use this code:
Func<Type, List<Type>> f = ty =>
{
var tysReturn = new List<Type>();
if (ty.BaseType != null)
{
tysReturn.Add(ty.BaseType);
}
tysReturn.AddRange(ty.GetInterfaces());
return tysReturn;
};
The function f will take a Type and return a list of its base type plus interfaces.
Hope it helps.
I know there are very similar questions but im not sure that any of them are exactly what i need. I have 2 methods that do exactly the same thing (so i dont need to override or anything) the only difference is the parameter and return types.
public List<List<TestResult>> BatchResultsList(List<TestResult> objectList)
{
}
public List<List<ResultLinks>> BatchResultsList(List<ResultLinks> objectList)
{
}
is there a neat way of doing this that doesnt involve duplciate code (the types are used inside the method).
public List<List<T>> BatchResultsList<T>(List<T> objectList)
{
foreach(T t in objectList)
{
// do something with T.
// note that since the type of T isn't constrained, the compiler can't
// tell what properties and methods it has, so you can't do much with it
// except add it to a collection or compare it to another object.
}
}
and if you need to limit the type of T so that you'll only process specific sorts of objects, make both TestResult and ResultLinks implement an interface, say, IResult. Then:
public interface IResult
{
void DoSomething();
}
public class TestResult : IResult { ... }
public class ResultLinks : IResult { ... }
public List<List<T>> BatchResultsList<T>(List<T> objectList) where T : IResult
{
foreach(T t in objectList)
{
t.DoSomething();
// do something with T.
// note that since the type of T is constrained to types that implement
// IResult, you can access all properties and methods defined in IResult
// on the object t here
}
}
When you call the method, you can of course omit the type parameter, since it can be inferred:
List<TestResult> objectList = new List<TestResult>();
List<List<TestResult>> list = BatchResultsList(objectList);
use generic methods
public List<List<T>> BatchResultsList<T>(List<T> objectList)
{
}
when you call it for TestResult:
BatchResultsList<TestResult>(testResultList)
for ResultLinks:
BatchResultsList<ResultLinks>(resultLinksList)
EDIT:
I presume that because it's the same code inside you 2 methods, TestResult & ResultLinks must implement a common interface, let's call it SomeInterface & a common constructor, let's choose the parameterless one:
you would declare and use the method like this:
public List<List<T>> BatchResultsList<T>(List<T> objectList)
where T:SomeInterface, new()
{
List<List<T>> toReturn = new List<List<T>>();
//to instantiate a new T:
T t = new T();
foreach (T result in objectList)
{
//use result like a SomeInterface instance
}
//...
return toReturn;
}
what about
public List<IList> BatchResultsList(List<IList> objectList)
{
}
Generic version:
public List<List<T>> BatchResultsList<T>(List<T> objectList){}