【问题标题】:Find parent class from property从属性中查找父类
【发布时间】:2015-02-21 20:13:09
【问题描述】:

下午好,

我不太确定如何表达我的问题,所以请原谅任何不相关的内容,如果我遗漏了任何重要的内容,请告诉我!我对 lambdas、regex 和 linq 也没有经验,所以请指出我做得不好/可能会做得更好的任何事情。

我的问题是:我可以得到一个类的引用,而我只知道一个属性吗?具体来说,在下面的代码 sn-p 中,我想将 propertyValues[0] 中的 0 的索引更改为存储在同一类上的变量。有没有类似this 的东西访问父级?

有关更多上下文,我在下面粘贴了相关的修剪代码。

return Regex.Replace ( originalString, "{(.*?)}", match =>
    User.user.properties.First( property =>
        property.id == match.ToString ().Substring ( 1, match.ToString ().Length - 2 ))
            .propertyValues[0].adjectives[0]);



public class Property
{

    public string id;
    public List<Value> propertyValues = new List<Value> ();
    public sbyte propertyIndex;

}

感谢您抽出宝贵时间阅读本文!

编辑

感谢您的反馈,Philip Stuyck 我会尽力解释得更好。

我正在寻找一种方法来获取对属性的父类的引用,或者一种在 lambda 表达式中创建局部变量的方法。为了说明,我有以下类和返回方法。

属性类,

public class Property
{

    public string id;
    public List<Value> propertyValues = new List<Value> ();
    public sbyte propertyIndex;

}

用户类,

public class User
{

    public static User user = new User ();

    internal List<Property> properties = new List<Property> ();
}

GetVariable 方法,

public static class GetVariable
{

    public static string FromUser ( string originalString )
    {

        return Regex.Replace ( originalString, "{(.*?)}", match => User.user.properties.First ( property => property.id == match.ToString ().Substring ( 1, match.ToString ().Length - 2 )).propertyValues[0].adjectives[0]);
    }
}

GetVariable.FromUser 方法应返回一个新字符串,该字符串已用来自User.user.properties 的字符串替换了括在括号中的子字符串的每个实例。因此,它可以传递“这是一个 {Example}。”,并返回“这是一个 Demo”(如果 User 类有一个 id 为 Example 的属性,并且值为 Demo)。

我的问题是与 GetVariable 方法有关,更具体地说,是最后一部分:propertyValues[0]。我希望索引(当前为 0)成为 Property 类上的变量,User.user.properties.First 委托正在查找该变量。

因此,理想情况下,它会像 User.user.properties.First ( property =&gt; property.id == match.ToString ()).propertyValues[property.propertyIndex] 一样简单,但我无法访问括号外的属性。

我希望这有助于解释它,尽管我觉得它仍然太复杂了。如果我能想到更好的方式来表达我的问题,我会这样做。另外,我很乐意通过评论澄清任何事情。

【问题讨论】:

  • 完全不明白你的意思。请完全改写。
  • @PhilipStuyck 感谢您的评论!我试图改写我的问题,我希望现在更清楚了。我不太擅长解释这类问题,所以请早点原谅我的糟糕工作。如果还是太模糊,请在 cmets 中询问,这样我可以尝试使其更清楚一点。再次感谢!

标签: c# regex linq


【解决方案1】:

简而言之,没有。如果你有一个对象的引用,你可以使用反射从中获取一个潜在的未知属性,但是当你有一个属性时你不能找到一个任意的对象。这是有道理的,因为如果您有一些名为 Id 的属性,它可能是任何对象的属性,那么 C# 甚至会如何尝试开始将其解析回类型 - 更不用说该类型的特定实例了。

如果你知道你有什么实例,你可以像这样使用反射:

var myProperty = myInstance.GetType().GetProperty("Id");
myProperty.SetMethod.Invoke(myInstance, new object[] {42});
//this will set the given property on the given 
//instance with the given value (42 in this example)
//GetMethod is also there 
//depending on what you need to do with it

但我要澄清的是,上述反射仅适用于 Properties,并且在您的示例中您有字段,因此您需要获取与属性有点不同的 FieldInfo。

但在上面的示例中似乎不清楚,看起来您既有实例又知道类型,所以为什么不能直接使用:

Regex.Replace ( 
   originalString, 
   "{(.*?)}", 
    match =>
        User.user.properties.First( property =>
        property.id == match.ToString().Substring( 1, 
                              match.ToString().Length - 2))
                .propertyValues[(int)property.propertyIndex]
                .adjectives[0]);

除非我不清楚你在问什么,否则它看起来会起作用吗?

更新

好的,我仍在尝试,因为您的最终目标不是很明确,但看起来您想要的是将匹配上下文包装在方法主体中,以便您可以访问在您失去范围之前多次找到匹配项。

类似这样的东西,我认为它是您正在寻找的东西:

return Regex.Replace ( 
   originalString, 
   "{(.*?)}", 
    match => 
    {
        var matchStr = match.ToString()
        var formattedMatch = matchStr.Substring(1, matchStr.Length - 2);
        var prop = User.user.properties.First(
                 property => property.id == formattedMatch);
        return prop.propertyValues[(int)prop.propertyIndex].adjectives[0];
    }

TL;DR

我可能应该提到你说你是 Linq 和 lambdas 的新手,本质上 Expression&lt;T&gt;LambdaExpression 是在执行时而不是在编译时编译的 Func&lt;TArgs..&gt;,所以你在做什么你写的c =&gt; c.Id == 42 正在创建一个看起来像这样的方法:

internal static int _closureVariable = 42;
public static bool checkName(Property prop)
{
     return prop.Id == _closureVariable;
}

它的处理和生成方式涉及更多,但最终结果是相似的。

所以在我的方法体示例中,我只是创建了一个更复杂的方法,其签名如下:

public static string matchRegex(Match match);

然后所有工作都在该方法签名中进行。重要的是要记住,当表达式上没有声明方法体时,return 关键字是隐式的(即c =&gt; c.Name == "some name" 隐式返回true)所以如果你有一个方法体(c =&gt; { ... })你需要声明返回明确地,否则它将返回无效。 (即c =&gt; { return c.Name == "some name"})。

【讨论】:

  • Tophallen,感谢您的回复。我想做与您的后一个示例类似的事情,但 property 引用在 properties.First 委托之外不存在。我也希望避免反思,但这可能是我必须做的。有没有办法在 lambda 表达式中分配引用?
  • 我不知道可以从委托中创建一个方法,非常感谢!
  • 我包含了一些关于如何以及为什么工作的解释,如果你关心的话,也许它会为你澄清一些关于 Linq 语法和表达式的事情:)
  • 这很有帮助,感谢您花时间概述它们如何为我工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多