gpt4 book ai didi

c# - "elegant"标识字段的方法?

转载 作者:太空狗 更新时间:2023-10-29 23:27:14 25 4
gpt4 key购买 nike

我正在编写一个作为程序员应用程序基础的系统,它需要检测他们对某些数据的访问。我主要可以使用属性来做到这一点,如下所示:

public class NiceClass {
public int x { get; set; }
}

然后我进入并调整 getset访问器,以便它们适本地处理访问。然而,这要求用户(应用程序员)将他们的所有数据定义为属性。

如果用户想要使用具有“正常”字段(而不是属性)的预先存在的类,我无法检测到这些访问。例子:
public class NotSoNiceClass {
public int y;
}

我无法检测到对 y 的访问.但是,我想允许使用预先存在的类。作为妥协,用户有责任在发生对此类数据的访问时通知我。例如:
NotSoNiceClass notSoNice;
...
Write(notSoNice.y, 0); // (as opposed to notSoNice.y = 0;)

类似的东西。相信我,我已经对此进行了非常彻底的研究,甚至直接分析字节码来检测访问也不可靠,因为可能存在间接性等。我确实需要用户通知我。

现在我的问题是:你能推荐一种“优雅”的方式来执行这些通知吗? (是的,我知道这整个情况一开始并不“优雅”;我试图不让它变得更糟;))。你会怎么做?

这对我来说是个问题,因为实际上情况是这样的:我有以下类(class):
public class SemiNiceClass {
public NotSoNiceClass notSoNice { get; set; }
public int z { get; set; }
}

如果用户想这样做:
SemiNiceClass semiNice;
...
semiNice.notSoNice.y = 0;

相反,他们必须做这样的事情:
semiNice.Write("notSoNice").y = 0;

哪里 Write将返回 notSoNice 的克隆,这就是我想要的 set无论如何都要做访问器(accessor)。然而,使用字符串非常难看:如果他们稍后重构该字段,他们将不得不检查他们的 Write("notSoNice")访问并更改字符串。

我们如何识别字段?我只能想到字符串、整数和枚举(即再次整数)。但:
  • 我们已经讨论过字符串的问题。
  • 整数是一种痛苦。它们更糟糕,因为用户需要记住哪个 int 对应哪个字段。重构同样困难。
  • 枚举(例如 NOT_SO_NICEZ,即 SemiNiceClass 的字段)简化了重构,但它们要求用户为每个类( SemiNiceClass 等)编写一个枚举,每个字段的值类(class)。这很烦人。我不想让他们讨厌我 ;)

  • 那么,我听到你问,为什么我们不能这样做(如下)?
    semiNice.Write(semiNice.notSoNice).y = 0;

    因为我需要知道正在访问什么字段,以及 semiNice.notSoNice不标识字段。这是字段的值,而不是字段本身。

    叹。我知道这很丑陋。相信我 ;)

    我将不胜感激建议。

    提前致谢!

    (另外,我无法为这个问题想出好的标签。如果你有更好的想法,请告诉我,我会编辑它们)

    编辑 #1: Hightechrider 的建议:表达式。

    不知道是不是 Write(x =>semiNice.y, 0)旨在基于我为我的问题编写的类( SemiNiceClass 等),或者它只是一个示例,但如果是前者,则它与结构不匹配:没有 y字段在 SemiNiceClass .您的意思是 Write(x =>semiNice.notSoNice.y, 0) ?

    我不确定你对我来说如何使用这个......我会发布我写的代码:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace Test.MagicStrings {

    public class MagicStringsTest {
    public static void Main(string[] args) {
    SemiNiceClass semiNice = new SemiNiceClass();
    // The user wants to do: semiNice.notSoNice.y = 50;
    semiNice.Write(x => semiNice.notSoNice.y, 50);
    }
    }

    public class SemiNiceClass {

    public NotSoNiceClass notSoNice { get; set; }
    public int z { get; set; }

    public SemiNiceClass() {
    notSoNice = new NotSoNiceClass();
    }

    public void Write(Func<object, object> accessor, object value) {
    // Here I'd like to know what field (y, in our example) the user wants to
    // write to.
    }

    }

    public class NotSoNiceClass {
    public int y;
    }

    }

    我如何在 Write 中获取该信息?我找不到任何方法从 Func<,> 中提取该信息.还有,为什么要写 semiNice.Write(x => semiNice.notSoNice.y, 50);而不是 semiNice.Write(() => semiNice.notSoNice.y, 50); ,因为我们没有使用 x为了任何东西?

    谢谢。

    编辑 #2: Hans Passant 的建议:用属性替换字段。

    这是我最初打算做的,但重新编译不是一种选择。

    编辑 #3 :Ben Hoffstein 的建议:动态代理;林福。

    我已经研究了很长时间,而且由于相对复杂的原因,我无法使用它。解释太长了,但请放心:如果我可以使用它,我会的。它比我目前的解决方案要简洁得多。

    最佳答案

    使用表达式,例如写(x =>semiNice.y,0)

    这种技术经常被用作避免魔法字符串的一种方式。

    例如

        public void Write<T,U>(T source, Expression<Func<T, U>> lambda, U value) 
    {
    var body = lambda.Body as MemberExpression;
    string memberName = body.Member.Name;
    if (body.Member.MemberType == MemberTypes.Field)
    {
    (body.Member as FieldInfo).SetValue(source, value);
    }
    else if (body.Member.MemberType == MemberTypes.Method)
    {
    (body.Member as MethodInfo).Invoke(source, new object[]{value});
    }
    Console.WriteLine("You wrote to " + memberName + " value " + value);
    }

    关于c# - "elegant"标识字段的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2739495/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com