【发布时间】:2010-04-29 17:40:18
【问题描述】:
我正在编写一个系统,它是程序员应用程序的基础,并且需要检测他们对某些数据的访问。我主要可以使用属性来做到这一点,如下所示:
public class NiceClass {
public int x { get; set; }
}
然后我进入并调整get 和set 访问器,以便它们适当地处理访问。但是,这要求用户(应用程序程序员)将他们的所有数据定义为属性。
如果用户想要使用具有“普通”字段(而不是属性)的预先存在的类,我无法检测到这些访问。示例:
public class NotSoNiceClass {
public int y;
}
我无法检测到对 y 的访问。但是,我想允许使用预先存在的类。作为妥协用户有责任在访问此类数据时通知我。例如:
NotSoNiceClass notSoNice;
...
Write(notSoNice.y, 0); // (as opposed to notSoNice.y = 0;)
类似的东西。相信我,我已经对此进行了非常彻底的研究,甚至直接分析字节码以检测访问由于可能存在间接等原因是不可靠的。我确实需要用户通知我。
现在我的问题是:您能推荐一种“优雅”的方式来执行这些通知吗? (是的,我知道这整个情况一开始并不“优雅”;我试图不让它变得更糟;))。你会怎么做?
这对我来说是个问题,因为实际上情况是这样的:我有以下课程:
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 访问器无论如何都要做的事情。但是,使用字符串非常难看:如果稍后他们重构该字段,他们将不得不检查他们的 Write("notSoNice") 访问并更改字符串。
我们如何识别该字段?我只能想到字符串、整数和枚举(也就是整数)。但是:
- 我们已经讨论过字符串的问题。
- 整数是一种痛苦。它们甚至更糟,因为用户需要记住哪个 int 对应于哪个字段。重构同样困难。
- 枚举(如
NOT_SO_NICE和Z,即SemiNiceClass的字段)便于重构,但它们要求用户为每个类(SemiNiceClass等)编写一个枚举,每个值都有一个类的领域。它很烦人。我不想让他们恨我;)
那么,我听到你问,为什么我们不能这样做(如下)?
semiNice.Write(semiNice.notSoNice).y = 0;
因为我需要知道正在访问什么字段,而semiNice.notSoNice 不识别字段。这是字段的值,而不是字段本身。
叹息。我知道这很丑陋。相信我;)
非常感谢您的建议。
提前致谢!
(另外,我无法为这个问题想出好的标签。如果您有更好的想法,请告诉我,我会编辑它们)
编辑 #1: Hightechrider 的建议:表达式。
我不知道Write(x =>semiNice.y, 0) 是基于我为我的问题编写的类(SemiNiceClass 等)还是只是一个示例,但如果是前者,它与结构:SemiNiceClass 中没有 y 字段。你是说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 的建议:动态代理;林福。
我已经对此进行了漫长而艰苦的研究,但由于相对复杂的原因,我无法使用它。解释太长了,但请放心:如果我可以使用它,我会的。它比我目前的解决方案要简洁得多。
【问题讨论】:
标签: c# field notifications identifier magic-string