- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想将派生类中声明的属性的一些支持字段存储在基类中包含的 protected 哈希表中。这种机制在派生类中的使用必须尽可能简单。
那么,我能否使用 MethodBase.GetCurrentMethod()
来提供有关调用属性的信息(getter - 属性是只读的),以便它可以被识别为唯一具有访问权限的属性到这个特定的支持领域?
编辑:
基本上,我想实现模式:
private SomeClass _someProperty = null;
private SomeClass SomeProperty
{
if (_someProperty == null)
{
_someProperty = new SomeClass();
}
return _someProperty;
}
看起来像这样:
private SomeClass SomeProperty
{
return GetProperty(delegate
{
var someProperty = new SomeClass();
return someProperty;
};
}
在基类
private System.Collections.Hashtable _propertyFields = new System.Collections.Hashtable();
protected T GetProperty<T>(ConstructorDelegate<T> constructorBody)
{
var method = new System.Diagnostics.StackFrame(1).GetMethod();
if (!_propertyFields.ContainsKey(method))
{
var propertyObject = constructorBody.Invoke();
_propertyFields.Add(method, propertyObject);
}
return (T)_propertyFields[method];
}
protected delegate T ConstructorDelegate<T>();
我这样做的原因是为了简化属性的使用。我使用私有(private)属性来创建一些对象并在类中使用它们。但是当我将它们的支持字段存储在同一个类中时,我对它们的访问权限与对属性的访问权限相同,所以我(指将来会创建一些派生类的用户)可能会不小心使用支持字段而不是属性,< strong>所以我想限制对支持字段的访问,同时允许创建对象并使用它。
我尝试像这样在支持字段上使用 ObsoleteAttribute:
[Obsolete("Don't use this field. Please use corresponding property instead.")]
private SomeClass __someProperty;
private SomeClass _someProperty
{
#pragma warning disable 0618 //Disable Obsolete warning for property usage.
get
{
if (__someProperty== null)
{
__someProperty = new SomeClass();
}
return __someProperty ;
}
#pragma warning restore 0618 //Restore Obsolete warning for rest of the code.
}
但是,首先,我不能强制用户使用这种模式,其次,在派生类中编写的代码太多,正如我上面提到的,我希望尽可能简单。
最佳答案
都不是MethodBase
也不MemberInfo
没有正确覆盖 Equals
和 GetHashCode
功能,但使用默认 RuntimeHelpers.GetHashCode
和 RuntimeHelpers.Equals
.所以你只能比较相同的实例,但不能比较相同的内容。在大多数情况下,这足以作为运行时缓存实例以重用它们。但不能保证这会稳定运行。
当您处理元数据时,请使用能够唯一标识它的内容。例如, MemberInfo.MetadataToken
.您可以编写自己的比较器并在哈希表中使用它:
public class MethodBaseComparer : IEqualityComparer<MethodBase>
{
public bool Equals(MethodBase x, MethodBase y)
{
if (ReferenceEquals(x, y))
return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
return x.MetadataToken.Equals(y.MetadataToken) &&
x.MethodHandle.Equals(y.MethodHandle);
}
public int GetHashCode(MethodBase obj)
{
return (obj.MetadataToken.GetHashCode() * 387) ^ obj.MethodHandle.GetHashCode();
}
}
通过反射限制对某些成员的访问不是一个好主意,因为其他受信任的代码可以使用反射来访问绕过您的检查的其他私有(private)数据。考虑通过重新设计您的类来限制访问。
另请查看 Code Access Security .
根据您的编辑更新。
您告诉您的属性是只读的。我想,只需将它们声明为 readonly
不是你的选择。看起来您想要延迟初始化属性值。在这种情况下,您将无法将它们声明为 readonly
.对吧?
也许你可以?
看看 Lazy<T>
类(class)。它在 dotnet 2.0 中不可用,但您可以轻松实现它,甚至可以使用 any existing implementation (just replace Func<T>
with your delegate) .用法示例:
public class Foo
{
private readonly Lazy<int> _bar = new Lazy<int>(() => Environment.TickCount, true);
// similar to your constructorBody - ^^^^^^^^^^^^^^^^^^^^^^^^^^^
private int Bar
{
get { return this._bar.Value; }
}
public void DoSomethingWithBar(string title)
{
Console.WriteLine("cur: {0}, foo.bar: {1} <- {2}",
Environment.TickCount,
this.Bar,
title);
}
}
优点:
如您所愿,这是一个惰性初始化。让我们测试一下:
public static void Main()
{
var foo = new Foo();
Console.WriteLine("cur: {0}", Environment.TickCount);
Thread.Sleep(300);
foo.DoSomethingWithBar("initialization");
Thread.Sleep(300);
foo.DoSomethingWithBar("later usage");
}
输出将是这样的:
cur: 433294875
cur: 433295171, foo.bar: 433295171 <- initialization
cur: 433295468, foo.bar: 433295171 <- later usage
请注意,值在第一次访问时初始化,以后不会更改。
属性被编译器写保护 - _bar
字段是 readonly
并且您无权访问 Lazy<T>
的内部字段.所以,没有任何意外的支持字段使用。如果你尝试你会得到类型不匹配的编译错误:
CS0029 Cannot implicitly convert type
System.Lazy<SomeClass>
toSomeClass
即使您通过 this._bar.Value
访问它,没有什么可怕的事情会发生,你会得到一个正确的值,就像你通过 this.Bar
访问它一样。属性(property)。
它更简单、更快速、更易于阅读和维护。
开箱即用的线程安全。
缺点:— (我没找到)
关于您的 hashtable
几分钱|基于设计:
关于c# - MethodBase 作为哈希表键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38589452/
我正在尝试 grep conf 文件中所有不以 开头的有效行 哈希(或) 任意数量的空格(0 个或多个)和一个散列 下面的正则表达式似乎不起作用。 grep ^[^[[:blank:]]*#] /op
我正在使用哈希通过 URL 发送 protected 电子邮件以激活帐户 Hash::make($data["email"]); 但是哈希结果是 %242y%2410%24xaiB/eO6knk8sL
我是 Perl 的新手,正在尝试从文本文件创建散列。我有一个代码外部的文本文件,旨在供其他人编辑。前提是他们应该熟悉 Perl 并且知道在哪里编辑。文本文件本质上包含几个散列的散列,具有正确的语法、缩
我一直在阅读 perl 文档,但我不太了解哈希。我正在尝试查找哈希键是否存在,如果存在,则比较其值。让我感到困惑的是,我的搜索结果表明您可以通过 if (exists $files{$key}) 找到
我遇到了数字对映射到其他数字对的问题。例如,(1,2)->(12,97)。有些对可能映射到多个其他对,所以我真正需要的是将一对映射到列表列表的能力,例如 (1,2)->((12,97),(4,1))。
我见过的所有 Mustache 文档和示例都展示了如何使用散列来填充模板。我有兴趣去另一个方向。 EG,如果我有这个: Hello {{name}} mustache 能否生成这个(伪代码): tag
我正在尝试使用此公式创建密码摘要以获取以下变量,但我的代码不匹配。不确定我做错了什么,但当我需要帮助时我会承认。希望有人在那里可以提供帮助。 文档中的公式:Base64(SHA1(NONCE + TI
我希望遍历我传递给定路径的这些数据结构(基本上是目录结构)。 目标是列出根/基本路径,然后列出所有子 path s 如果它们存在并且对于每个子 path存在,列出 file从那个子路径。 我知道这可能
我希望有一个包含对子函数的引用的散列,我可以在其中根据用户定义的变量调用这些函数,我将尝试给出我正在尝试做的事情的简化示例。 my %colors = ( vim => setup_vim()
我注意到,在使用 vim 将它们复制粘贴到文件中后尝试生成一些散列时,散列不是它应该的样子。打开和写出文件时相同。与 nano 的行为相同,所以一定有我遗漏的地方。 $ echo -n "foo"
数组和散列作为状态变量存在限制。从 Perl 5.10 开始,我们无法在列表上下文中初始化它们: 所以 state @array = qw(a b c); #Error! 为什么会这样?为什么这是不允
在端口 80 上使用 varnish 5.1 的多网站设置中,我不想缓存所有域。 这在 vcl_recv 中很容易完成。 if ( req.http.Host == "cache.this.domai
基本上,缓存破坏文件上的哈希不会更新。 class S3PipelineStorage(PipelineMixin, CachedFilesMixin, S3BotoStorage): pa
eclipse dart插件在“变量” View 中显示如下内容: 在“值”列中可见的“id”是什么意思? “id”是唯一的吗?在调试期间,如何确定两个实例是否相同?我是否需要在所有类中重写toStr
如何将Powershell中的命令行参数读入数组?就像是 myprogram -file file1 -file file2 -file file3 然后我有一个数组 [file1,file2,fil
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
例如,我有一个包含 5 个元素的哈希: my_hash = {a: 'qwe', b: 'zcx', c: 'dss', d: 'ccc', e: 'www' } 我的目标是每次循环哈希时都返回,但没
我在这里看到了令人作呕的类似问题,但没有一个能具体回答我自己的问题。 我正在尝试以编程方式创建哈希的哈希。我的问题代码如下: my %this_hash = (); if ($user_hash{$u
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
这个问题已经有答案了: Java - how to convert letters in a string to a number? (9 个回答) 已关闭 7 年前。 我需要一种简短的方法将字符串转
我是一名优秀的程序员,十分优秀!