#c# #generics #interface
#c# #общие методы #интерфейс
Вопрос:
Я хотел бы создать прокси-класс, который сможет извлекать имя метода, указанного в аргументе, и экземпляр параметра с универсальным завершением (иначе говоря, мне не нужны nameof() или волшебные строки).
Например, я хотел бы иметь возможность делать что-то вроде
public interface ITestInterface
{
void TestMethod(Param myParam)
}
var proxy = new Proxy<ITestInterface>();
var param = new Param();
proxy.WriteName(x => ITestInterface.TestMethod(param));
и прокси-класс должен иметь возможность повторно запрашивать имя метода и выполнять tostring для экземпляра параметра :
public class Proxy<T>
{
public void WriteName(Something something)
{
Console.WriteLine(something.MethodName); // write "TestMethod"
Console.WriteLine(something.Parameter.ToString()); // use the tostring of the instance object
}
}
Спасибо за вашу помощь
Ответ №1:
Я бы сказал, что было бы нелегко поддерживать все возможные сценарии, но для того, что вы описали в вопросе, вы можете попробовать использовать деревья выражений:
public class Proxy<T>
{
public void WriteName(Expression<Action<T>> something)
{
// TODO: add correct handling for not supported operations
if (something.Body is MethodCallExpression mc)
{
Console.WriteLine(mc.Method.Name);
foreach (var arg in mc.Arguments)
{
if (arg is MemberExpression me amp;amp; me.Expression is ConstantExpression cnst)
{
var val = me.Member.MemberType switch
{
MemberTypes.Field => ((FieldInfo)me.Member).GetValue(cnst.Value),
MemberTypes.Property => ((PropertyInfo)me.Member).GetValue(cnst.Value),
_ => null
};
Console.WriteLine(val);
}
}
}
}
}
И использование:
var proxy = new Proxy<ITestInterface>();
var param = new Param();
proxy.WriteName(t => t.TestMethod(param)); // actually many more can be passed here
Ответ №2:
Если я правильно понимаю, вы можете попробовать это:
public class Proxy<T>
{
public void WriteName(Expression<Action> action)
{
var methodCallExp = (MethodCallExpression)action.Body;
Console.WriteLine(methodCallExp.Arguments.First().ToString());
Console.WriteLine(methodCallExp.Method.Name);
}
}
и вызвать прокси-класс следующим образом:
var proxy = new Proxy<ITestInterface>();
proxy.WriteName(() => new ConcreteTestInterface().TestMethod(param));