1

The program gets information about a class such as method/feilds/properties names return types parametres using reflection. Now I let the user type in the name and see the data. When working with the .Net libraries or my own assemblies works fine. But when I ask it to find stuffs from a different assembly that I made it just cant find it. Here are the code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace CSharpVenkat
{

    class Program
    {

        static void DataFinder()
        {
            try
            {
                //Using bool as I didnt want to make a nested for loop

                bool consoleColorSet = false;

                for (;;)
                {

                    if (consoleColorSet == false)
                    {
                        Console.BackgroundColor = ConsoleColor.Black;

                        Console.Clear();

                        consoleColorSet = true;
                    }

                    Console.Write("Class: ");
                    string s = Console.ReadLine();

                    Console.WriteLine();

                    Type t = Type.GetType(s) as Type;

                    if (t != null)
                    {
                        //Methods

                        MethodInfo[] methods = t.GetMethods();

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Methods of class \"" + t.FullName + "\"");
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.WriteLine();

                        if (methods.Length <= 0)
                        {

                            Console.WriteLine("None!");

                        }

                        foreach (MethodInfo method in methods)
                        {

                            Console.WriteLine(method.ToString());

                        }

                        Console.WriteLine();
                        Console.WriteLine();

                        //Constructors

                        ConstructorInfo[] constructors = t.GetConstructors();

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Constructor of class \"" + t.FullName + "\"");
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.WriteLine();

                        if (constructors.Length <= 0)
                        {

                            Console.WriteLine("None!");

                        }

                        foreach (ConstructorInfo constructor in constructors)
                        {

                            Console.WriteLine(constructor.Name + " " + constructor.ToString());

                        }

                        Console.WriteLine();
                        Console.WriteLine();

                        //Fields

                        FieldInfo[] fields = t.GetFields();

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Fields of class \"" + t.FullName + "\"");
                        Console.ForegroundColor = ConsoleColor.White;

                        Console.WriteLine();

                        if (fields.Length <= 0)
                        {

                            Console.WriteLine("None!");

                        }

                        foreach (FieldInfo field in fields)
                        {

                            Console.WriteLine(field.FieldType.Name + " " + field.Name);

                        }

                        Console.WriteLine();
                        Console.WriteLine();

                        //Properties

                        PropertyInfo[] properties = t.GetProperties();

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Properties of class \"" + t.FullName + "\"");
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.WriteLine();

                        if (properties.Length <= 0)
                        {

                            Console.WriteLine("None!");

                        }

                        foreach (PropertyInfo property in properties)
                        {

                            Console.WriteLine(property.PropertyType.Name + " " + property.Name);

                        }


                        break;
                    }

                    else
                    {

                        Console.WriteLine("Invalid ! Please check your namespace and class name!");
                        Console.WriteLine();

                    }
                }
            }

            //Really Incase something goes wrong, I dont know anything that could go wrong here still!

            catch (Exception e)
            {

                Console.WriteLine("Programm stopped responding! due to  error", e.GetType().Name);

            }


        }

        //Main method

        static void Main(string[] args)                    
        {

            DataFinder();


            Console.ReadKey();
        }


    }
}

Now I know I could get the assembly of the class I am trying to execute by doing

Assembly a = Assembly.GetAssembly(typeof(ClassName));
Type t = a.GetType(s); //s is the userput

But the problem is I want to let the Console user do it not me writing the class name. I cant pass a string inside typeof either. The problem is going like: If I want the the "Type" of the user input I need to get the assembly first but to get the assembly I need to get the "Type". How do I solve this.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Reza Taibur
  • 263
  • 3
  • 10

2 Answers2

2

If the input is a partial name (like ListBox instead of System.Windows.Controls.ListBox), you can use this :

var types = AppDomain.CurrentDomain.GetAssemblies()
    .Select(x => Assembly.Load(x.FullName))
    .SelectMany(x => x.GetExportedTypes())
    .Where(x => x.Name == s)
    .ToList();

Note: You may get more than 1 result sometimes.

If you input is a full name, you can use this :

var type = AppDomain.CurrentDomain.GetAssemblies()
    .Select(x => Assembly.Load(x.FullName))
    .Select(x => x.GetType(s))
    .FirstOrDefault(x => x != null);
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44
1

Given just a string containing a type name (e.g. My.Namespace.MyType or MyType), there is no built-in way to resolve that to the either an Assembly or Type instance. As I see it, you have 2 options:

  1. If the assembly containing the type is in a location that you know about (for example, maybe all the assemblies are in the same directory as the main "entry point" assembly), you can manually load the assemblies and try to find the type.
  2. If the assembly is not in a well-known location, you're going to have to ask the user to either enter the assembly name or the full path to the assembly. See Type.GetType or Assembly.Load or Assembly.LoadFrom.
Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
  • Thanks although user "SLaks" already said to this Assembly.Load(). Worked great! – Reza Taibur May 24 '16 at 20:38
  • There is one other option, if you own all the assemblies from which the user can specify types. The Managed Extensibility Framework allows you to mark up types with special attributes that allow assemblies to be easily cataloged and queried for types. This would allow you to skip all the manual loading of assemblies required by step 1. You would instead load up a catalog of the possible assemblies and then query the catalog. https://msdn.microsoft.com/en-us/library/dd460648.aspx – Michael Gunter May 24 '16 at 20:41