Необходимо вызывать методы класса по имени (т.е. мне известна строка с именем метода класса). Нашел только один более менее подходящий способ - использовать рефлексию.
public class Simple
{
public string SimpleMethod(string param1)
{
return param1;
}
}
//и собственно вызов
Simple simple = new Simple();
var method = typeof(Simple).GetMethod("SimpleMethod");
object[] param = new object[] {"Hello World!"};
string result = method.Invoke(sample, param) as string;
Но как я понимаю от такого способа сильно падает производительность. Есть ли более "элегантное решение"?
Тут предлагают использовать System.Linq.Expressions:
namespace Research.UnitTests
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Reflection;
[TestClass]
public class Research
{
[TestMethod]
public void TestWithTiming()
{
var calculator = new Calculator();
//Получить ссылку на метод "Calculate".
MethodInfo methodInfo = typeof(Calculator).GetMethod(
"Calculate",
new Type[] { typeof(int) });
//Создать параметр.
ParameterExpression param = Expression.Parameter(typeof(int), "i");
//Создать "точку вызова".
var thisParameter = Expression.Constant(calculator);
//Создать выражение для вызова метода.
//Если бы метод был статический, то "точка вызова" была бы
//лишней.
MethodCallExpression methodCall = Expression.Call(
thisParameter,
methodInfo,
param);
//Создать лямбда-выражение.
Expression<Func<int, string>> lambda =
Expression.Lambda<Func<int, string>>(
methodCall,
new ParameterExpression[] { param }
);
//Откомпилировать лямбда-выражение в Func<>.
Func<int, string> func = lambda.Compile();
//Замеряем производительность вызова c использованием рефлексии.
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
for (int i = 0; i < 1000000; i++)
{
string result = (string)methodInfo.Invoke(calculator, new object[] { i });
}
watch.Stop();
System.Console.WriteLine(watch.ElapsedMilliseconds);
//Замеряем производительность вызова по имени.
watch = new System.Diagnostics.Stopwatch();
for (int i = 0; i < 1000000; i++)
{
string result = func(i);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
//Замеряем производительность прямого вызова.
watch = new System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
string result = calculator.Calculate(i);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
}
}
public class Calculator
{
public string Calculate(int i)
{
string result = string.Empty;
//Референсный код.
DateTime now = DateTime.Now;
DateTime nextDay = now.AddDays(i);
result = nextDay.ToString();
return result;
}
}
}
Результат:
1930 (рефлексия)
1530 (expression)
1519 (прямой вызов)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Вот так создаю меню правой кнопки мыши над DataGridView :
Здесь перебирает слишком долго, пишу на 35 фрейморке, на 4 хорошо идёт EnumerateDirectories и EnumerateFiles, А мне нужно на 3