Я пытаюсь создать макет интерфейса ISomeService, используя библиотеку Moq, которая будет обертывать его реальную реализацию SomeService< /code>.
Сейчас я делаю это вручную следующим образом:
Код: Выделить всё
var instance = new SomeService();
var mock = new Mock();
mock.Setup(x => x.Run(It.IsAny()))
.Returns(x => instance.Run(x));
ЧТО Я СДЕЛАЛ
Что у меня есть для настройки() часть
Код: Выделить всё
// (x)
var mockParameter = Expression.Parameter(typeof(T), "x");
// It.IsAny()
var isAnyMethod = typeof(It).GetMethod(nameof(It.IsAny));
var isAny = parameters.Select(x => Expression.Call(isAnyMethod.MakeGenericMethod(x.ParameterType))).ToArray();
// x.Run(It.IsAny())
mockCall = Expression.Call(mockParameter, method, isAny);
Код: Выделить всё
// (x) => x.Run(It.IsAny())
var mockLambda = Expression.Lambda(mockCall, mockParameter);
Код: Выделить всё
public ISetup Setup(Expression expression)
Код: Выделить всё
var setupMethod = typeof(Mock)
.GetMethods()
.Where(x => x.Name == nameof(mock.Setup) && x.GetParameters()[0].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func)).First()
.MakeGenericMethod(method.ReturnType);
var setupResult = setupMethod.Invoke(mock, new object[] { mockLambda });
System.InvalidOperationException: 'Операции с поздним связыванием не могут выполняться над типами или методами для который содержит true.
что имеет смысл, но разочаровывает.
ЧТО Я ПОПЫТАЛ< /strong>
Я попытался привести тип результата к типу объекта
Код: Выделить всё
var converted = Expression.Convert(mockCall, typeof(object));
Код: Выделить всё
// (x) => (object)x.Run(It.IsAny())
var mockLambda = Expression.Lambda(converted, mockParameter);
System.ArgumentException: 'Неподдерживаемое выражение: (object)x.Run( It.IsAny())'
Чтобы сделать эту работу, я добавил несколько операторов else if для типов значений, где для заданного типа результата я возвращаю определенное выражение но поддерживать и расширять это кошмар. Для классов я использую объект, и, по крайней мере, эта часть работает.
Для типов значений, определяемых пользователем, я добавил общий метод
Код: Выделить всё
void SetupUnsuportedMethod(MethodInfo methodInfo)
ВОПРОС[/b]
Есть ли способ сделать этот код полностью универсальным? Может быть, есть лучший способ решить эту проблему? Или мне придется придерживаться этого неприятного решения?
Подробнее здесь: https://stackoverflow.com/questions/793 ... erations-c
Мобильная версия