Creating a type from a generic argument using Reflection?

  • Thread starter Thread starter Ympostor
  • Start date Start date
Y

Ympostor

Why can't I do this (it gives a syntactic error):?

foreach (System.Reflection.PropertyInfo oProp in
oObject.GetType().GetProperties())
{
if ((oProp.PropertyType.IsGenericType) &&
(oProp.PropertyType.GetGenericTypeDefinition() ==
(typeof(IList<>))))
{
Type oMyType = oProp.PropertyType.GetGenericArguments()[0];

List<oMyType> MyNewVariable = new List<oMyType>();
}
}

Thanks in advance.

--
 
3 problems; first: the compiler isn't going to believe you, in the same way
that it doesn't believe the following:

if(control is TextBox) {
TextBox tb = control;
}

second; you have checked IList<T>, and then assigned to List<T>.

third; oMyType is not a type; you can't use dynamic T in this way; you would
need to use reflection to create the generic type (or to invoke a generic
method typed to that type).

Marc
 
Marc Gravell escribió:
third; oMyType is not a type; you can't use dynamic T in this way; you would
need to use reflection to create the generic type (or to invoke a generic
method typed to that type).

How can I do it via Reflection then?

Thanks for your answer.

--
 
Full example:

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public static void Main()
{
TestGenerics(
new List<int>(),
new Collection<Control>(),
new double[] {});
}
public static void TestGenerics(params object[] values)
{
MethodInfo mi = typeof(Program).GetMethod("TestGeneric");
foreach (object obj in values)
{
Type type = obj.GetType();
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.IsGenericType &&
interfaceType.GetGenericTypeDefinition()==typeof(IList<>)) {
mi.MakeGenericMethod(interfaceType.GetGenericArguments()).Invoke(null,
new object[] {obj});
break;
}

}
}
}
public static void TestGeneric<T>(IList<T> item)
{
Console.WriteLine("Made it: T=" + typeof(T).Name);
}
}
 
See my other post; I recommend the "branch to a generic method" approach, as
it means you only use reflection briefly to change to the second method;
this means that the code within the method *accessed* via reflection can be
fully compiled and optimised, and use generic syntax rather than reflection.
Note also that the inner-method would typically be private, so would require
a binding-flag; I only made it public to make it easy to obtain via
GetMethod().

Marc
 
Marc Gravell escribió:
Full example:

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public static void Main()
{
TestGenerics(
new List<int>(),
new Collection<Control>(),
new double[] {});
}
public static void TestGenerics(params object[] values)
{
MethodInfo mi = typeof(Program).GetMethod("TestGeneric");
foreach (object obj in values)
{
Type type = obj.GetType();
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.IsGenericType &&
interfaceType.GetGenericTypeDefinition()==typeof(IList<>)) {
mi.MakeGenericMethod(interfaceType.GetGenericArguments()).Invoke(null,
new object[] {obj});
break;
}

}
}
}
public static void TestGeneric<T>(IList<T> item)
{
Console.WriteLine("Made it: T=" + typeof(T).Name);
}
}


Cool!!! I think that this is what I was looking for! I'll report soon.

Thanks very much.

--
 
Marc Gravell escribió:
See my other post; I recommend the "branch to a generic method" approach, as
it means you only use reflection briefly to change to the second method;
this means that the code within the method *accessed* via reflection can be
fully compiled and optimised, and use generic syntax rather than reflection.

Ok this solution finally works for me. Thanks very much.

Note also that the inner-method would typically be private, so would require
a binding-flag; I only made it public to make it easy to obtain via
GetMethod().

But I don't understand this, if I make the method private (which I think
it's the correct way) I can't access it with GetMethod, how can I do it?

Regards.

--
 
Ympostor escribió:
But I don't understand this, if I make the method private (which I think
it's the correct way) I can't access it with GetMethod, how can I do it?

Nevertheless, I have done it with:

BindingFlags.Static | BindingFlags.NonPublic

However, isn't there a way to obtain the MethodInfo statically?
Something like this:

GetMethod(MyClass.MyStaticMethod);

Thanks again.

--
 
If the method was non-generic (or we knew the T in advance), then you may be
able to do this by declaring a matching delegate signature, creating a
delegate pointing to the method, and then inspecting the delegate instance's
Method property (a MethodInfo).

However, AFAIK it is only possible to do this for concrete methods, and you
need to reference the generic method definition (not a closed implementation
there-of); so I don't know if it can be done (how, for instance, would you
declare the variable for this step?

There may be a non-delegate way of accessing the method, but given that we
are using reflection anyhow, an extra GetMethod isn't likely to be much of
an issue.

Marc
 
Back
Top