Мое приложение работает с динамической загрузкой dll на основе настроек из базы данных (имена файлов, классов и методов). Чтобы облегчить, ускорить и уменьшить использование рефлексии, я хотел бы иметь кэш....
Следуя идее, что использование:
MethodInfo.Invoke
Нет ничего результативного (Эффект отражения - Создать делегат (Свойства С#)) Я хотел бы перевести любой вызов методам. Я подумал о чем-то, что будет работать следующим образом:
public static T Create<T>(Type type, string methodName) // or
public static T Create<T>(MethodInfo info) // to use like this:
var action = Create<Action<object>>(typeof(Foo), "AnySetValue");
Одним из требований является то, что все параметры могут быть объектами.
Я пытаюсь разобраться с выражениями, и до сих пор у меня есть что-то вроде этого:
private void Sample()
{
var assembly = Assembly.GetAssembly(typeof(Foo));
Type customType = assembly.GetType("Foo");
var actionMethodInfo = customType.GetMethod("AnyMethod");
var funcMethodInfo = customType.GetMethod("AnyGetString");
var otherActionMethod = customType.GetMethod("AnySetValue");
var otherFuncMethodInfo = customType.GetMethod("OtherGetString");
var foo = Activator.CreateInstance(customType);
var actionAccessor = (Action<object>)BuildSimpleAction(actionMethodInfo);
actionAccessor(foo);
var otherAction = (Action<object, object>)BuildOtherAction(otherActionMethod);
otherAction(foo, string.Empty);
var otherFuncAccessor = (Func<object, object>)BuildFuncAccessor(funcMethodInfo);
otherFuncAccessor(foo);
var funcAccessor = (Func<object,object,object>)BuildOtherFuncAccessor(otherFuncMethodInfo);
funcAccessor(foo, string.Empty);
}
static Action<object> BuildSimpleAction(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
Expression<Action<object>> expr =
Expression.Lambda<Action<object>>(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method), obj);
return expr.Compile();
}
static Func<object, object> BuildFuncAccessor(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
Expression<Func<object, object>> expr =
Expression.Lambda<Func<object, object>>(
Expression.Convert(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method),
typeof(object)),
obj);
return expr.Compile();
}
static Func<object, object, object> BuildOtherFuncAccessor(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
Expression<Func<object, object, object>> expr =
Expression.Lambda<Func<object, object, object>>(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj, value);
return expr.Compile();
}
static Action<object, object> BuildOtherAction(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
Expression<Action<object, object>> expr =
Expression.Lambda<Action<object, object>>(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj,
value);
return expr.Compile();
}
public class Foo
{
public void AnyMethod() {}
public void AnySetValue(string value) {}
public string AnyGetString()
{ return string.Empty; }
public string OtherGetString(string value)
{ return string.Empty; }
}
Есть ли способ упростить этот код? (Я считаю, что можно создать метод, используя только общий). И когда у вас есть 3, 4, 5, какие-либо параметры, как я?
Я думал, что если бы что-то вроде этого:
но у меня будет больше одного параметра (в действии или функции), этот параметр (первый параметр) - объект для выполнения. Возможно ли это?