Как получить тип класса по его имени?
class Program
{
static void Main<T>(string[] args)
{
string className = "MyClass";
var myClassType = Activator.CreateInstance(Type.GetType(className));
var res = method<myClassType>();
}
public static List<T> method<T>()
{
return new List<T>();
}
}
public class MyClass
{
public string anyString { get; set; }
public int anyInt { get; set; }
}
Красивым способом это не сделать, нужно использовать reflection и MakeGenericMethod:
string className = "ConsoleApplication1.MyClass";
var myClassType = Type.GetType(className);
var method = typeof(Program).GetMethod("method", BindingFlags.Static | BindingFlags.Public);
var genericMethod = method.MakeGenericMethod(myClassType);
// вернет список нужного типа - List<MyClass>
dynamic list = genericMethod.Invoke(null, null);
Activator
отдаст Вам ссылку типа object
на созданный объект класса по полному квалифицированному имени класса:
Type type = Type.GetType("ConsoleApplication17.MyClass");
object instance = Activator.CreateInstance(type);
Если Вы хотите обращаться к методам и полям объекта класса напрямую, то Вам нужно будет в явном виде указать конкретный тип. Для этого можно использовать, например, безопасное приведение типа:
var propertyValue = (instance as MyClass)?.anyInt;
Если Вы не хотите явно указывать тип в коде, то можете воспользоваться механизмом динамической типизации:
try
{
dynamic dynamicInstance = instance;
var propertyValue = dynamicInstance.anyInt
}
catch(RuntimeBinderException ex)
{
Console.WriteLine("Wrong type specified: " + ex.Message);
}
Обратите внимание на обработку RuntimeBinderException
.
Для получения типа по имени нужно дописывать пространство имен, а лучше использовать полное имя с указанием имени сборки.
Получить тип лучше из сборки. Предварительно её загрузив. Для .Net Core это выглядит так
static Assembly LoadAssembly(string fileName)
{
var Dir = AppContext.BaseDirectory;
string path = Path.Combine(Dir, fileName);
Assembly assembly = null;
if (File.Exists(path))
{
try
{
var asm = System.Runtime.Loader.AssemblyLoadContext.GetAssemblyName(path);
assembly = Assembly.Load(asm);
}
catch (Exception)
{
assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
}
}
return assembly;
}
Ну а из сборки можешь получить и тип используя GetType
Посмотри здесь .Net Core, AppDomain, WCF, RPC маршалинг по Tcp/Ip свой велосипед
Там и поиск типа, методов с параметрами по умолчанию, параметрами массивами, Дженерик методами, методов расширений в том числе Linq, делегатов, объектов поддерживающие IDynamicMetaObjectProvider (DynamicObject,ExpandoObject,JObject). В том числе поиск дженерик метода с автовыводм типа по параметрам
Например там реализован динамический вызов дженерик метода
// Test Generic Method с параметрами по умолчанию
//public string GenericMethodWithDefaulParam<K, V>(Dictionary<K, V> param1, K param2, int param3 = 4, string param4 = "Test")
var @Int32 = wrap.GetType("System.Int32");
resGM = TO.GenericMethodWithDefaulParam(dict, 99);
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
resGM = TO.GenericMethodWithDefaulParam(pp(@Int32, "System.String"), dict, 99);
Console.WriteLine("Вызов дженерик метода с аргументами типов " + resGM);
// Test Generic Method с параметрами массивом
// public string GenericMethodWithParams<K, V>(Dictionary<K, V> param1, K param2, params string[] args)
resGM = TO.GenericMethodWithParams(dict, 99, "First", "Second");
Console.WriteLine("Вызов дженерик метода с автовыводом типов " + resGM);
Где TO это динамик вызывающий метод по Tcp/IP, но его можно приязать к типу и вызвать методы локально. Просто для поиска метода из-за перегрузок, дефолтных параметрах, параметрах массивов не всегда простая задача
Для обычного .Net поиск сборки выглядит так. Сразу прошу прощения за Руслиш.
private static Type НайтиТип(string type)
{
Type result = Type.GetType(type, false);
if (result != null)
{
return result;
}
foreach (System.Reflection.Assembly tmpAasembly in
System.AppDomain.CurrentDomain.GetAssemblies())
{
result = tmpAasembly.GetType(type);
if (result != null)
{
return result;
}
}
return null;
}
public object ПолучитьТипИзСборки(string type, string путь)
{
var result = НайтиТип(type);
if (result != null)
return new AutoWrap(result);
string ошибка;
string path;
System.Reflection.Assembly assembly;
if (File.Exists(путь))
assembly = System.Reflection.Assembly.LoadFrom(путь);
else
{
path = Path.Combine(Path.GetDirectoryName(typeof(string).Assembly.Location), путь);
if (File.Exists(path))
{
var ИмяСборки = AssemblyName.GetAssemblyName(path).FullName;
assembly = System.Reflection.Assembly.Load(ИмяСборки);
}
else
{
ошибка = " Не найден файл " + путь + " или " + path;
MessageBox.Show(ошибка);
throw new COMException(ошибка);
}
}
result = assembly.GetType(type);
if (result != null)
{
return new AutoWrap(result);
}
ошибка = " неверный тип " + type + " в сборке " + assembly.Location;
MessageBox.Show(ошибка);
throw new COMException(ошибка);
// return null;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Задача: есть DataGridView, в который выводится разная нужная информацияCо временем информации, которую хотят видеть, много прирастает
Желательно по Си, не доходит как можно сделать
1) Я создал отдельный класс и унаследовал в нем LabelМожно ли его теперь как-то добавить на ToolBox? После компиляции он не появляется