Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c lambda表达式+反思问题_C#_.net_Reflection_Lambda - Fatal编程技术网

C# c lambda表达式+反思问题

C# c lambda表达式+反思问题,c#,.net,reflection,lambda,C#,.net,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", someT

这主要是出于教育目的。我正在尝试创建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();
我的InputMapper类包含使用Map方法创建的所有映射的集合。CreateInstance将通过映射循环尝试转换用户输入,并将其分配给lambda表达式中使用的属性。在循环时,它将保存抛出的任何FormatException的集合

我的问题是:

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

使现代化 斯基特博士想了解更多关于我的意图的信息

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

更新2
经过一番牵手,乔恩和丹把我带到了那里。你能提出改进建议吗?这里是我的答案:

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

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

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

public class InputMapper<TSource> where TSource : new()
{
    public void Map<TResult>(string input,
                             Expression<Func<TSource, TResult>> projection,
                             string text)
    {
        ...
    }
}
更新:有关我认为您正在尝试做的工作的示例,请参阅

更新2:看起来在我发布这篇文章之前你就已经明白了。好的无论如何,我将把它放在那里作为参考,尽管它不是一个非常有效的实现

下面是一个演示程序

class CustomType
{
    public int Integer { get; set; }
    public double Double { get; set; }
    public bool Boolean { get; set; }
    public string String { get; set; }

    public override string ToString()
    {
        return string.Format("int: {0}, double: {1}, bool: {2}, string: {3}", Integer, Double, Boolean, String);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        var mapper = new InputMapper<CustomType>();

        mapper.Map("10", x => x.Integer, "Unable to set Integer property.");
        mapper.Map("32.5", x => x.Double, "Unabled to set Double property.");
        mapper.Map("True", x => x.Boolean, "Unable to set Boolean property.");
        mapper.Map("Hello world!", x => x.String, "Unable to set String property.");

        var customObject = mapper.Create();

        Console.WriteLine(customObject);

        Console.ReadKey();
    }
}
然后,您大概要做的是根据propertyExpression计算出您希望根据用户输入设置的属性。是这样吗

我不完全清楚为什么你不想这样定义它,尽管:

class InputMapper<T>
{
    public void Map<TProperty>(string input,
                               Action<TProperty> propertySetter,
                               string errorMessage);
}
然后,用法将类似于:

mapper.Map<int>(
    "some user input",
    value => someType.IntProperty = value,
    "Input was not an integer"
);
请注意,Map函数在内部必须处理将用户输入解析为适当类型的问题,可能需要使用诸如Convert.ChangeType之类的简单方法。

更新:有关我认为您正在尝试执行的操作的工作示例,请参阅

更新2:看起来在我发布这篇文章之前你就已经明白了。好的无论如何,我将把它放在那里作为参考,尽管它不是一个非常有效的实现

下面是一个演示程序

class CustomType
{
    public int Integer { get; set; }
    public double Double { get; set; }
    public bool Boolean { get; set; }
    public string String { get; set; }

    public override string ToString()
    {
        return string.Format("int: {0}, double: {1}, bool: {2}, string: {3}", Integer, Double, Boolean, String);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        var mapper = new InputMapper<CustomType>();

        mapper.Map("10", x => x.Integer, "Unable to set Integer property.");
        mapper.Map("32.5", x => x.Double, "Unabled to set Double property.");
        mapper.Map("True", x => x.Boolean, "Unable to set Boolean property.");
        mapper.Map("Hello world!", x => x.String, "Unable to set String property.");

        var customObject = mapper.Create();

        Console.WriteLine(customObject);

        Console.ReadKey();
    }
}
然后,您大概要做的是根据propertyExpression计算出您希望根据用户输入设置的属性。是这样吗

我不完全清楚为什么你不想这样定义它,尽管:

class InputMapper<T>
{
    public void Map<TProperty>(string input,
                               Action<TProperty> propertySetter,
                               string errorMessage);
}
然后,用法将类似于:

mapper.Map<int>(
    "some user input",
    value => someType.IntProperty = value,
    "Input was not an integer"
);
请注意,Map函数在内部必须处理将用户输入解析为适当类型的问题,可能需要使用Convert.ChangeType之类的简单方法

如果lambda中的表达式不是属性引用,则可以添加一些检查以抛出更好的异常



如果lambda中的表达式不是属性引用,您可以添加一些检查以抛出更好的异常。

这取决于-someType.IntProperty/BoolProperty的类型是什么?假设sometType实际上应该分别读取someType。@david-int和bool…需要并使用lambda作为参数和不只是一个枚举来指示类型?@Josh-该参数不用于指示类型。它用于指示要尝试使用Map方法提供的用户输入设置的属性。这取决于-someType.IntProperty/BoolProperty的类型是什么?假设sometType实际应分别读取someType。@david-int和bool…是否有任何特定的原因希望并使用lambda作为参数,而不仅仅是一个枚举来进行设置指示类型?@Josh-该参数不用于指示类型。它用于指示要尝试使用Map方法提供的用户输入设置的属性。我在问题中提供了一些详细信息,我正在查找如何为projection param描述的属性赋值的示例代码。获取错误3找不到类型或命名空间名称“TResult”是吗缺少using指令或程序集引用?当试图编译时。TSource也是一样。@Ronnie:我怀疑你没有像我那样声明这个方法-TResult和TSource是类型参数;TResult是该方法的类型参数,TSource是该类型的类型参数。你说得对。我快到了。现在正在获取TResult的错误。这是我的代码:@Ronnie:您不能将列表作为成员字段,因为没有一致的TProperty,不同的属性将具有不同的类型。您必须使InputMapping从一些非泛型基继承,并使您的字段成为列表或类似的内容。我在问题中提供了一些详细信息,我正在寻找如何为属性赋值的示例代码
m描述。获取错误3找不到类型或命名空间名称“TResult”是否缺少using指令或程序集引用?当试图编译时。TSource也是一样。@Ronnie:我怀疑你没有像我那样声明这个方法-TResult和TSource是类型参数;TResult是该方法的类型参数,TSource是该类型的类型参数。你说得对。我快到了。现在正在获取TResult的错误。这是我的代码:@Ronnie:您不能将列表作为成员字段,因为没有一致的TProperty,不同的属性将具有不同的类型。您必须使InputMapping从一些非泛型基继承,并使您的字段成为列表或类似的内容。谢谢!我来试一试。我很高兴有人能理解我。谢谢!我来试一试。很高兴有人理解了我的意思。看起来您建议接受一个动作参数,使调用代码负责将输入分配给属性。我不想那样做。这是InputMapper的责任。我只想告诉类我希望它创建的类型,以及尝试使用什么用户输入来设置属性,以及稍后将向用户显示的错误消息。错误信息部分与我真正遇到的问题无关,我不应该把它包括在我的问题中。@Ronnie:好的,很公平;那就接受我的第一个建议吧。您当然可以从表达式转换为属性设置器;但是正如Jon在他的回答中指出的,如果调用代码给您带来的不是属性表达式,那么您必须首先决定要做什么,以及当传递给您的属性无法设置时要做什么。只是一些需要注意的事情。非常感谢。但愿我能将2个答案标记为已接受。Jon让我快了一点。看起来你建议接受一个动作参数,让调用代码负责将输入分配给属性。我不想那样做。这是InputMapper的责任。我只想告诉类我希望它创建的类型,以及尝试使用什么用户输入来设置属性,以及稍后将向用户显示的错误消息。错误信息部分与我真正遇到的问题无关,我不应该把它包括在我的问题中。@Ronnie:好的,很公平;那就接受我的第一个建议吧。您当然可以从表达式转换为属性设置器;但是正如Jon在他的回答中指出的,如果调用代码给您带来的不是属性表达式,那么您必须首先决定要做什么,以及当传递给您的属性无法设置时要做什么。只是一些需要注意的事情。非常感谢。但愿我能将2个答案标记为已接受。乔恩让我更快到达那里。
public T CreateInstance() 
{
    T result = new T();
    foreach (var lambda in map) 
    {
        ((PropertyInfo)((MemberExpression)lambda.Body).Member).SetValue(result, null, propertyValueForLambdaThatYouStored);  
    }
    return result;
}