【发布时间】:2014-05-21 14:13:56
【问题描述】:
我想编写一个为任何接口创建模拟的方法。
public T GetMock<T>(IDictionary<string, object> data) where T : class
我首先只关心属性获取器。所有 getter 都应该返回存储在字典中的值。属性名称是此字典中的键。以下代码说明了预期用途:
public interface IFoo
{
string Property1 { get; }
int Property2 { get; }
DateTime Property3 { get; }
}
[Test]
public void TestY()
{
var data = new Dictionary<string, object>
{
{"Property1", "Hello"},
{"Property2", 5},
{"Property3", DateTime.Today}
};
var mock = GetMock<IFoo>(data);
Assert.AreEqual("Hello", mock.Property1);
Assert.AreEqual(5, mock.Property2);
Assert.AreEqual(DateTime.Today, mock.Property3);
}
关键是我想模拟任何界面。所以我的通用模拟创作看起来像:
public T GetMock<T>(IDictionary<string, object> data) where T : class
{
var mock = new Mock<T>();
var type = typeof(T);
var properties = type.GetProperties();
foreach (var property in properties)
{
var attributeName = property.Name;
var parameter = Expression.Parameter(type);
var body = Expression.Property(parameter, attributeName);
var lambdaExpression = Expression.Lambda<Func<T, object>>(body, parameter);
Func<object> getter = () => data[attributeName];
mock.Setup(lambdaExpression).Returns(getter);
}
return mock.Object;
}
它应该可以工作,但类型转换存在问题。测试失败并显示一条消息:
System.ArgumentException : 'System.Int32' 类型的表达式不能 用于返回类型'System.Object'
我想我错过了一些转换 lambda。有什么建议可以解决这个问题吗?
【问题讨论】:
-
哪一行给了你这个例外?
var lambdaExpression...? -
没错。行
var lambdaExpression = Expression.Lambda<Func<T, object>>(body, parameter); -
我希望这是因为您试图从
Func<T, object>返回一个(例如)int参数,但很抱歉我不知道如何解决它:p跨度> -
这也是我的猜测。
标签: c# .net generics lambda moq