Поиск метода, который вы хотите вызвать, является достаточно простым отражением. Сложной частью является выяснение имени метода для вызова. Иногда самое простое, что можно сделать, - это создать выражение и посмотреть, как его компилятор соединяет.
Например, это:
Expression<Func<Dictionary<string, string>, string>> expr = d => d["test"];
Если вы проверяете (или Dump()
, если вы используете LINQPad) переменную expr
, вы сможете бродить по сгенерированному дереву выражений и смотреть на такие вещи, как информация о методе в узле Call
.
В вашем случаекажется, что вы хотите вызвать get_Item
в классе Dictionary<string, string>
. Требуется ссылка на объект и строковый параметр для ключа. Экземпляр объекта будет значением свойства Fields
из предоставленного ContactCustomFieldsFacet
, поэтому нам нужно его получить.
Сборка всего объекта вручную может выглядеть примерно так:
public static Func<ContactCustomFieldsFacet, string> MakeAccessor(string key)
{
var tFacet = typeof(ContactCustomFieldsFacet);
var piFields = tFacet.GetProperty("Fields");
var miFieldsGet = piFields.PropertyType.GetMethod("get_Item");
var param = Expression.Parameter(tFacet, "facet");
var lambda = Expression.Lambda<Func<ContactCustomFieldsFacet, object>>
(
Expression.Call
(
// Instance for invocation: param.Fields
Expression.MakeMemberAccess(param, piFields),
// Method to call
miFieldsGet,
// Call arguments
Expresion.Constant(key)
),
param
);
return lambda.Compile();
}
При вызове этого метода вы получите Func<>
, который возвращает значение для определенного key
, установленного во время создания Func<>
. Например:
var fnGetTest = MakeAccessor("test");
var value = fnGetTest(someFacetInstance);
Все это предполагает, что в словаре хранятся ссылочные типы - строка работает нормально. Если это тип значения (например, int), вам нужно указать значение Convert
, равное object
.