2016-05-24 1 views
1

Программа получает информацию о классе, таком как метод/feilds/properties, возвращает параметры возвращаемого типа с использованием отражения. Теперь я позволяю пользователю вводить имя и видеть данные. При работе с библиотеками .Net или моими собственными сборками отлично работает. Но когда я прошу его найти материал из другой сборки, я сделал это просто не могу найти его. Вот кодПолучить сборку с использованием строки

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(); 
     } 


    } 
} 

Теперь я знаю, что я мог бы получить сборку класса я пытаюсь выполнить, делая

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

Но проблема, я хочу, чтобы позволить пользователю консоли сделать это не я пишу название класса. Я не могу передать строку внутри typeof. Проблема будет такой: если я хочу «Тип» ввода пользователя, мне нужно сначала собрать сборку, но чтобы получить сборку, мне нужно получить «Тип». Как я могу это решить.

+0

Вы должны знать, какой тип сборки находится, вероятно, спрашивая пользователя. – SLaks

+0

Как превратить эту строку в тип сборки? –

+1

'Assembly.Load' принимает имя сборки. – SLaks

ответ

1

Учитывая только строку, содержащее имя типа (например, My.Namespace.MyType или MyType), нет встроенного способа решить, что либо к примеру в Assembly или Type. Как я понимаю, у вас есть 2 варианта:

  1. Если сборка, содержащая тип находится в таком месте, что вы знаете о (например, может быть, все узлы находятся в том же каталоге, что и основной «точкой входа» сборка), вы можете вручную загрузить сборки и попытаться найти тип.
  2. Если сборка не находится в известном месте, вам нужно попросить пользователя либо ввести имя сборки, либо полный путь к сборке. См. Type.GetType или Assembly.Load или Assembly.LoadFrom.
+0

Спасибо, хотя пользователь «SLaks» уже сказал этой Assembly.Load(). Отлично! –

+0

Существует еще один вариант, если у вас есть все сборки, из которых пользователь может указать типы. Рамка Managed Extensibility Framework позволяет вам выделять типы со специальными атрибутами, которые позволяют легко сортировать сборки и запрашивать их для типов. Это позволит вам пропустить всю ручную загрузку сборок, необходимых для шага 1. Вместо этого вы загрузите каталог возможных сборок и затем запросите каталог. https://msdn.microsoft.com/en-us/library/dd460648.aspx –

1

Если вход частичное имя (как ListBox вместо System.Windows.Controls.ListBox), вы можете использовать это:

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

Примечание: Вы можете получить более 1 результат иногда.

Если вход полное имя, вы можете использовать это:

var type = AppDomain.CurrentDomain.GetAssemblies() 
    .Select(x => Assembly.Load(x.FullName)) 
    .Select(x => x.GetType(s)) 
    .FirstOrDefault(x => x != null);