Design Time Reflection

Hello.

I'm creating a custom control with desing time support.

For a property MyItems that is a collection of BaseItem's, I need to allow the user to add as many items he wish on a form I created (all in design time).

The problem: I have a number of classes that derived from BaseItem, and I want that the user will be able to select from a combobox all optional elements by using reflection of some sort, so that we I create a new BaseItem derived class, I don't want to change the combobox.

How can I do it




Answer this question

Design Time Reflection

  • Get It Over With

    I'll try, but before that, another problem:

    when using:

    Reflection.TypeTools.FindDerivedTypes(typeof(Form));

    on run time, its fine.

    But, on design time, it throws Exception object not set bla bla, I trace it back to the command:

    Assembly.GetEntryAssembly()

    which in desing time returns null.

    Do you know why



  • Buckley

     eligazit wrote:

    nice of you to give a sample with variable name: namespace....

     

    lol! sorry bout that haha.

    glad you fixed it. I'll mark it as answered.



  • Ney André de Mello Zunino

    Hi Jelle, great code, as always.

    One question due,

    I want to get the classes from a specifiec namespace on my project.

    I guess its in the Assembly.GetEntryAssembly(), but how excatly I do it

     



  • Alfred LOK20932

    Don't know why atm. I hope I'll finally get my machine back tomorrow. I'll get back to you about this unless you figure it out yourself in the meantime.



  • kab122

    Ok, got it:

    for desing time, I should use:

    Assembly.GetExecutingAssembly()

    and not:

    Assembly.GetEntryAssembly()

    this is because the first assembly returns the code that is currently excuting while the second one gets the process excutable, so it will not work an desing time, no excutable...

    Thanx for the help

    p.s

    nice of you to give a sample with variable name: namespace....

     



  • Mark Marsh

    Hey Eli,

    You can iterate over all the types in an assembly and check inheritance and all with IsAssignableFrom and IsSubClassOf. Here's a piece from our library that does the stuff that you request. Use FindDerivedTypes.



        public static class TypeTools
        {
            private static void AddReferencedAssemblies(
                Hashtable nameToAssemblyMap, Assembly parent, bool deep )
            {
                ArrayList loadedAssemblies = new ArrayList();

                foreach( AssemblyName assemblyName in parent.GetReferencedAssemblies() )
                {
                    if( !nameToAssemblyMap.Contains( assemblyName.FullName) )
                    {
                        Assembly child = Assembly.Load( assemblyName );
                        nameToAssemblyMap.Add( assemblyName.FullName, child );
                        loadedAssemblies.Add( child );
                    }
                }

                if( deep )
                {
                    foreach( Assembly child in loadedAssemblies )
                    {
                        AddReferencedAssemblies( nameToAssemblyMap, child, deep );
                    }
                }
            }

            public static ICollection GetReferencedAssemblies( Assembly root, bool deep )
            {
                Hashtable nameToAssemblyMap = new Hashtable();
                nameToAssemblyMap.Add( root.FullName, root );
               
                if( deep )
                {
                    AddReferencedAssemblies( nameToAssemblyMap, root, deep );
                }
               
                return nameToAssemblyMap.Values;
            }

            public static Type[] FindDerivedTypes( Type type, Assembly root, bool deep )
            {
                ArrayList result = new ArrayList();

                ICollection assemblies = GetReferencedAssemblies( root, deep );
                foreach( Assembly assembly in assemblies )
                {
                    foreach( Type subType in assembly.GetTypes() )
                    {
                        if( type.IsAssignableFrom( subType ) && !subType.IsAbstract )
                        {
                            result.Add( subType );
                        }
                    }
                }

                return (Type[]) result.ToArray( typeof( Type ) );
               
            }
            public static Type[] FindDerivedTypes( Type type )
            {
                return FindDerivedTypes( type, Assembly.GetEntryAssembly(), true );
            }
    }


     

    Oh... and credit to my collegue Peter Verswyvelen who build this code .



  • Sarang-Sarang

    Last one for tongiht...

    I've got the type now, how can I create the class from it

    Type t = .... got the type I want to create;

    BaseItem item = new <t>();

    Where BaseItem is the base class for t, always.

     

     



  • Bill Armstrong

    Thanks man!

    I think you will have to add a bit of code to FindDerivedTypes. Something like this:



            public static Type[] FindDerivedTypes( Type type, Assembly root, bool deep, string namespace )
            {
                ArrayList result = new ArrayList();
                ICollection assemblies = GetReferencedAssemblies( root, deep );
                foreach( Assembly assembly in assemblies )
                {
                    foreach( Type subType in assembly.GetTypes() )
                    {
                        if( type.IsAssignableFrom( subType ) && !subType.IsAbstract && subType.Namespace == namespace )
                        {
                            result.Add( subType );
                        }
                    }
                }

                return (Type[]) result.ToArray( typeof( Type ) );
               
            }


     

    Could you try that



  • salloum

    Ah, right. With the type, use Activator.CreateInstance to create the type.

  • Design Time Reflection