How cast parent into child to call right function in C#

Viewed 343

I Work on c#/Code first I've a Parent Class abstract public class form_base {} and severals differents childs class. Here one of them

 public class form_Frais : form_base    {
}

I've a view with all form_base, but when i click on one, I open a common template. I just need change the mapping according to child type in changing the controler/Function by an URL

Then In my form_base I had this :

 public T Cast<T>(object o)
    {
        return (T)o;
    }

    public dynamic converttt(Type LeTyp)
    {
        MethodInfo castMethod = GetType().GetMethod("Cast").MakeGenericMethod(new[] { LeTyp });
        dynamic castedObject = castMethod.Invoke(Activator.CreateInstance(LeTyp), new object[] { this });
        return castedObject;
    }

I've split my project in 2 part (engine/Web) My classes are define in engine

My problem is to fill my list of all form_base in web part. I use this function in controler part

 public ActionResult demandeur()
    {
        object model;

            model = new {  formsList = (from f in CurrentDBContext.forms_base  select f).ToList().getCardModel(false) };
        }

        return View("demandeur", model);
    }

And In web I create extension methods (I won't see in engine part) public static partial class extensions {

    public static List<formListItem> getCardModel(this List<form_base> items, bool envalidation)
    {
        List<formListItem> model = new List<formListItem>();
        if (items != null && items.Count > 0)
        {
            foreach (var item in items)
            {
                Type LeTyp = item.GetType().BaseType;
                dynamic castedObject = item.converttt(LeTyp);//Pb here not good type : System.Data.Entity.DynamicProxies.form_Frais_353DEAA5...' ne contient pas de définition pour 'getCardModel''

                model.Add(castedObject.getCardModel(envalidation));
            }
        }
        return model;
    }

    public static formListItem getCardModelBase(this form_base f)
    {
        formListItem model = new formListItem();
        model.id = f.id;
        model.libelle = f.title;
        model.libelleType = f.formType.title;
        model.libelleStatut = f.StatutInterneLibelle;
        model.demandeur = f.demandeur.fullName;
        model.idtype = f.formType.id;
        return model;
    }
 public static formListItem getCardModel(this form_Frais form, bool envalidation)
    {
        formListItem model = ((form_base)form).getCardModelBase();
        model.URL = "/forms/NoteFrais/InitForm"; //The good URL
        model.envalidation = envalidation;
        return model;
    }
}

I try to put all in extension part like that:

 public static T Cast<T>(object o)
    {
        return (T)o;
    }


    public static List<formListItem> getCardModel(this List<form_base> items, bool envalidation)
    {
        List<formListItem> model = new List<formListItem>();
        if (items != null && items.Count > 0)
        {
            foreach (var item in items)
            {
                Type LeTyp = item.GetType().BaseType;
                MethodInfo castMethod = item.GetType().BaseType.GetMethod("Cast").MakeGenericMethod(new[] { LeTyp });
                dynamic castedObject = castMethod.Invoke(null, new object[] { item });

                model.Add(castedObject.getCardModel(envalidation));
            }
        }
        return model;
    }

    public static formListItem getCardModelBase(this form_base f)
    {
        formListItem model = new formListItem();
        model.id = f.id;
        model.libelle = f.title;
        model.libelleType = f.formType.title;
        model.libelleStatut = f.StatutInterneLibelle;
        model.demandeur = f.demandeur.fullName;
        model.idtype = f.formType.id;
        return model;
    }

But I've error in item.GetType().BaseType.GetMethod("Cast").MakeGenericMethod(new[] { LeTyp }); cause GetMethod("Cast") return null

All my research come from here

UPDATE

In resume, In first try, I've problem of type class return dynamicproxy... And in static version, I can't find method Cast..

I try

 MethodInfo[] methodInfos = LeTyp.GetMethods(BindingFlags.Public | BindingFlags.Static);

But My array is empty... then my problem in static version will be hwo save correctly my Case function??? and use it in extension method

UPDATE 3

I find the problem in static mode I need tu put Cast function in note_frais class and use it

 Type LeTyp = item.GetType().BaseType;
                //MethodInfo[] methodInfos = LeTyp.GetMethods(BindingFlags.Public | BindingFlags.Static);
                MethodInfo MI = LeTyp.GetMethod("Cast");//<T>.getMethod(cast)
                MI = MI.MakeGenericMethod(typeof(form_base));
                dynamic t = MI.Invoke(null, new object[] { item });

                model.Add(t.getCardModel(envalidation));

But now I've same pb in 2 parts :

//Pb here not good type : System.Data.Entity.DynamicProxies.form_Frais_353DEAA5...' ne contient pas de définition pour 'getCardModel''

Thanks for your help? I read lot of things but now I'm completly lost.

2 Answers

Instead of:

GetMethod("Cast")

...try this overload:

GetMethod("Cast", new Type[] { typeof(Object) })

More observations...

The Cast<T> method of class form_base is not static. (See above to get this one.)

The class form_base doesn't define any public static methods.

(Side note, I'm not sure why the class extensions is defined as partial.)

The Cast<T> method in class extensions is static, but is not an extension method.

To get this one, you can use this overload, on type extensions:

typeof(extensions).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Object) }, null)

If you did define the Cast<T> extension method in class extensions:

public static partial class extensions {
    public static T Cast<T>(this form_base b, object o) {/*…*/}
}

...then you could get it with the same overload on type extensions, by modifying the types argument:

typeof(extensions).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(form_base), typeof(Object) }, null)

Finally... With a simple sample it's good

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApp1
{
  abstract public class form_base
  {
    public Guid Guid { get; set; }

}
public class form_Frais : form_base
{
    public int MonInt { get; set; }

    public static T Cast<T>(object o)
    {
        return (T)o;
    }
}
public class form_Avoir : form_base
{
    public int MonInt { get; set; }

    public static T Cast<T>(object o)
    {
        return (T)o;
    }
}

public static class extensions
{
    public static int GetCardModel(this form_Avoir form)
    {
        return form.MonInt * 100;
    }

    public static int GetCardModel(this form_Frais form)
    {
        return form.MonInt * form.MonInt;
    }
}

public class TOTO
{
    public static int GetCardModel(form_Avoir form)
    {
        return form.MonInt * 100;
    }

    public static int GetCardModel(form_Frais form)
    {
        return form.MonInt * form.MonInt;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
        form_Frais nf = new form_Frais();
        nf.Guid = Guid.NewGuid();
        nf.MonInt = 2;
        List<form_base> lst = new List<form_base>();
        //MethodInfo[] methodInfos = typeof(form_base).GetMethods(BindingFlags.Public | BindingFlags.Static);
        lst.Add(nf);
        form_Avoir av = new form_Avoir();
        av.Guid = Guid.NewGuid();
        av.MonInt = 5;
        lst.Add(av);

        foreach (dynamic f in lst)
        {
            Console.WriteLine(TOTO.GetCardModel(f)); // OK
            //Type LeTyp = f.GetType();
            //MethodInfo MI = LeTyp.GetMethod("Cast");//<T>.getMethod(cast)
            //MI = MI.MakeGenericMethod(typeof(form_base));
            //dynamic t = MI.Invoke(null, new object[] { f });
            //Console.WriteLine(t.GetCardModel());// Error 
        }
    }
  }
}

My error was to thought that extension methods was include in object. In fact not. It seems but not really. I just change with a method with parameter instead of extension

Related