Reputation: 917
I would like to have a class that handles population of lists of data from a drop down that can take any type as I would rather have the external code looking like:
listProvider.For<AnEnumType>().And<AClass>.GetLists();
than
listProvider.ForEnum<AnEnumType>().ForClass<AClass>.GetLists();
Here is the example code
public class Foo
{
public void DoSomething<T>
{
if(typeof(T).IsEnum)
{
//Do Something
} else if (typeof(T).IsClass)
{
var bar = new Bar();
//Problem How to call bar as type T must be a reference type?
bar.GetData<T>()
}
}
}
public class Bar
{
public IProvideList<T> GetData() where T : class
{
//Do Something
}
}
public interface IProvideList<T> T : class
{
}
At compile time the complier doesn't know that T is a class, but I know it will at runtime. I can call this with reflection:
bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));
however, I can't cast the result back to (IProvideList) when invoking the method because T must be a referenceType
Is there any way to get around this?
Upvotes: 2
Views: 133
Reputation: 917
I eventually managed to get around this by doing reflection:
bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));
Then not attempting to cast the result, but accessing all methods and functions I required for the result via reflection to so:
var listProviderType = typeof (IProvideList<>).MakeGenericType(typeof (T));
var result = istProviderImplType.GetMethod("MethodINeedToCall").Invoke(listProviderImpl, null);
Not exactly the nicest code I know but it achieves the result I want.
Upvotes: 0
Reputation: 1333
do you have to use where T : class
in bar? if not try this.
public class Foo
{
public void DoSomething<T>()
{
if(typeof(T).IsEnum)
{
//Do Something
} else if (typeof(T).IsClass)
{
var bar = new Bar();
//Problem How to call bar as type T must be a reference type?
bar.GetData<T>();
}
}
}
public class Bar
{
public IProvideList<T> GetData<T>() //where T : class
{
//Do Something
}
}
public interface IProvideList<T> //where T : class
{
}
Upvotes: 1
Reputation: 7525
Instead of just Bar
you can use Bar<T>
and it all falls naturally to:
public void DoSomething<T>
{
if(typeof(T).IsEnum)
{
//Do Something
}
else if (typeof(T).IsClass)
{
//Here you know T
var bar = new Bar<T>();
bar.GetData()
}
}
....
public class Bar<T>
{
public IProvideList<T> GetData<T>() where T : class
{
//Do Something
}
}
Upvotes: 1