c#lambda表达式+反思问题

Ron*_*rby 1 .net c# reflection lambda

这主要是出于教育目的.我正在尝试创建在此示例中使用的InputMapper类:

var mapper = new InputMapper<SomeType>();
mapper.Map("some user input", someType => someType.IntProperty, "Input was not an integer");
mapper.Map("some user input", someType => someType.BoolProperty, "Input was not a bool");

SomeType someTypeInstance = mapper.CreateInstance();
Run Code Online (Sandbox Code Playgroud)

我的InputMapper类包含使用Map()方法创建的所有映射的集合.CreateInstance()将遍历映射,尝试转换用户输入并将其分配给lambda表达式中使用的属性.当它循环时,它将保存抛出的任何FormatExceptions的集合.

我的问题是:

  • 在InputMapper.Map()方法中,lambda参数类型应该是什么?
  • 在InputMapper.CreateInstance()方法中,如何尝试在我创建的T实例上设置属性?

谢谢!

更新

斯凯特博士要求提供有关我的意图的更多信息.

InputMapper类将用于将用户输入分配给任何对象的成员,负责将用户输入转换为属性类型.可以从上面的示例推断出类的接口.

更新2

握了几手,乔恩和丹,把我带到了那里.你能建议改进吗?这就是我所拥有的:http://pastebin.com/RaYG5n2h

Jon*_*eet 5

对于您的第一个问题,该Map方法应该是通用的.例如:

public class InputMapper<TSource> where TSource : new()
{
    public void Map<TResult>(string input,
                             Expression<Func<TSource, TResult>> projection,
                             string text)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在值得注意的是,你的lambda表达式代表属性getter,但可能你想调用属性setter.这意味着您的代码不是编译时安全的 - 例如,可能存在只读的映射属性.此外,没有什么可以限制lambda表达式引用属性.它可以做任何事情.你必须加入执行时间防范.

一旦你已经找到了属性setter虽然,你只需要创建的实例TSource使用new TSource()(注意,构造函数约束TSource以上),然后进行适当的转换和调用属性setter.

如果没有关于你要做什么的更多细节,我担心给出一个更详细的答案并不是非常容易.

编辑:解决该属性的代码看起来像这样:

var memberExpression = projection.Body as MemberExpression;
if (memberExpression == null)
{
    throw new ArgumentException("Lambda was not a member access");
}
var propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo == null)
{
    throw new ArgumentException("Lambda was not a property access");
}
if (projection.Parameters.Count != 1 ||
    projection.Parameters[0] != memberExpression.Expression)
{
    throw new ArgumentException("Property was not invoked on parameter");
}
if (!propertyInfo.CanWrite)
{
    throw new ArgumentException("Property is read-only");
}
// Now we've got a PropertyInfo which we should be able to write to - 
// although the setter may be private. (Add more tests for that...)
// Stash propertyInfo appropriately, and use PropertyInfo.SetValue when you 
// need to.
Run Code Online (Sandbox Code Playgroud)