views:

98

answers:

2

It's there a way to invoke a method and the return type is strong typed ?

There is an example of code

 public static IQueryable<T> FilterVersion<T>(this Table<T> t, IVersionIndexFilter version)
      where T : class
    {
      try
      {
        // Define the new type of my table
        Type versionTableType = Type.GetType(typeof(T).AssemblyQualifiedName.Replace(typeof(T).FullName, string.Concat(typeof(T).FullName, VersionIndexTableExtensionName)));
        // Get the method info generic with a custom helper
        var getTableType = MethodInfoHelper.GetGenericMethod(typeof(DataContext), "GetTable", new Type[] { versionTableType }, new Type[] { }, typeof(Table<>).MakeGenericType(typeof(Table<>).GetGenericArguments()[0]), BindingFlags.Public | BindingFlags.Instance);
        // Get the object with a invoke but invoke return object, i need he return a Table<vesrionTableType>
        var joinTable = getTableType.Invoke(t.Context, null);
        // Put my new object in anonymous class
        var result = new { FromT = t, InnerT = joinTable };
        // Write the type of the property and is {System.Object InnerT}
        Console.Write(result.GetType().GetProperty("InnerT"));

}

I need my Console.Write(result.GetType().GetProperty("InnerT")); return a Table<versionTableType> It's there a way i cand do that ? Any suggestion ?

There is my GetGenericMethod

public static MethodInfo GetGenericMethod(Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType, BindingFlags flags)
    {
      if (genericArgTypes == null)
      {
        genericArgTypes = new Type[] { };
      } 

      MethodInfo genericMethod = (from m in t.GetMethods(flags)
                                  where m.Name == name
                                  && m.GetGenericArguments().Length == genericArgTypes.Length
                                  && m.GetParameters().Select(pi => pi.ParameterType.IsGenericType ? pi.ParameterType.GetGenericTypeDefinition() : pi.ParameterType).SequenceEqual(argTypes) &&
                                  (returnType == null || (m.ReturnType.IsGenericType ? m.ReturnType.GetGenericTypeDefinition() : m.ReturnType) == returnType)
                                  select m).FirstOrDefault();

      if (genericMethod != null)
      {
        return genericMethod.MakeGenericMethod(genericArgTypes);
      }

      return null;
    }

I get my method info generic correctly. The probleme is when i assign to another property the result of my invoke is an object. I need to strong type my result

EDIT : It's a good idea the static method CreateResult but not enough ... there is what i try to do after with my value

 NewExpression exResult = Expression.New(result.GetType().GetConstructor(new Type[] { t.GetType(), typeof(Table<>).MakeGenericType(versionTableType) }), new List<Expression>() { outer, inner }, result.GetType().GetProperty("FromT"), result.GetType().GetProperty("InnerT"));

There is the error i got after try the technique

Argument type 'System.Data.Linq.Table`1[Nms.Media.Business.Manager.Data.Linq.ImageLibraryItemBinaryLocaleVersionIndex]' does not match the corresponding member type 'System.Object'

Thanks

+3  A: 

EDIT: Okay, since your question edit it looks like you're already calling MakeGenericMethod. Good.

Now, once you've managed to invoke the method, there's then the matter of making an appropriate anonymous type. I would suggest you create a generic type and use Type.MakeGenericType on the generic type definition, then construct an instance of that. Alternatively, you could have another generic method which is strongly typed, and invoke that with reflection in a similar way. That method could use an anonymous type:

 public object CreateResult<TTable, TJoin>(TTable t, TJoin joinTable)
 {
     return new { FromT = t, InnerT = joinTable };
 }

You could call your generic MethodInfo helper to make it easier to invoke this.

Jon Skeet
getTableType.MakeGenericMethod(versionTableType).Invoke ... doent's work because return an object, and not my type
Cédric Boivin
It's *declared* to return `object`, but it will actually return the right type. That type is only known at execution, so to build an anonymous type with the right property type, you'll need to use reflection again.
Jon Skeet
It's a good idea
Cédric Boivin
A: 

I Auto resolve my solutions, inspired from Jon Skeet answer.

I create a class generic

public class ConvertTable<TOuter, TInner>
    where TInner : class
    where TOuter : class
  {
    public TOuter FromT { get; set; }
    public TInner InnerT { get; set; }
    public ConvertTable(TOuter fromT, TInner innerT)
    {
      FromT = fromT;
      InnerT = innerT;
    }
  }
Cédric Boivin