- 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/
我想将派生类中声明的属性的一些支持字段存储在基类中包含的 protected 哈希表中。这种机制在派生类中的使用必须尽可能简单。 那么,我能否使用 MethodBase.GetCurrentMetho
只是一个简单的观察。 property MethodBase.IsConstructor不适用于static构造函数,并且文档没有提及这一事实(引用:“true如果此方法是由ConstructorIn
只是一个简单的观察。 property MethodBase.IsConstructor不适用于 static 构造函数,并且文档没有提及这个事实(引用:“true 如果此方法是由 Construct
我的源代码中几乎每个函数都有以下代码。 string methodName = MethodBase.GetCurrentMethod().Name; 我的问题是 考虑到反射是一件代价高昂的事情,是否
我正在从 C++ 过渡到 C#,我有一个方法调用让我感到困惑。我想我也许能猜出它的作用,但如果专家能直接告诉我,我将不胜感激: WDResult returnValue = (WDResult)Inv
我正在使用带有 Lucene 引擎的后端 (.Net C#) 创建一个日志系统,并且我正在记录每个方法请求。 为此,我在后端创建了一个服务引用,WebService 方法参数之一是 Reflectio
我正在尝试使用此 post 中的类但它需要一个 MethodBase 才能运行。 我读了What is the fastest way to get a MethodBase object?但我找不到
我编写了一个日志类和一个函数,如下代码所示: Log(System.Reflection.MethodBase methodBase, string message) 每次我记录一些东西时,我也会记录
是否有等效于 MethodBase.GetCurrentMethod 的可移植类库? 我是 PCL 的新手。我只是在研究是否可以使用 PCL 来保存一些肯定会在 Silverlight 上使用并且可能
我有两个函数的 MethodBases: public static int Add(params int[] parameters) { /* ... */ } public static int
我想捕获在使用 invoke 方法调用的方法中抛出的异常。 public void TestMethod() { try { method.Invoke(comman
首先,很抱歉,如果之前有人问过这个问题。我进行了相当全面的搜索,没有发现任何类似的东西,但我可能遗漏了一些东西。 现在回答问题:我试图通过反射调用构造函数,但没有成功。基本上,我有一个要克隆的对象,因
有什么区别以及对代码的影响? 关于性能和限制,什么更适合? 新属性: - [调用文件路径属性] - [CallerMemberName] - [来电号码] 现在它们在 .NET 4 中也可用(它很容易
我正在将开源库从常规 .NET 4 Client Profile 移植到 DNX Core 5.0。有相当多的库更改,属性或方法被移动或完全删除。我看过this answer但它在我的情况下不起作用,
我正在将一个开源库从常规 .NET 4 客户端配置文件移植到 DNX Core 5.0。有相当多的库更改,属性或方法被移动或完全删除。我看过this answer但它在我的情况下不起作用,因为该方法已
我一直在为这个问题绞尽脑汁,但我找不到答案。 我知道 MethodBase.GetCurrentMethod 但我很好奇是否有等效项来获取当前正在执行的 Delegate(如果有一个正在执行,那就是)
我看到在 .NET 中实现登录时使用 StackFrame 和 MethodBase 的两个独立代码。 我知道 MethodBase 类提供有关方法和构造函数及其来源的信息。 StackFrame 表
如何从 MethodBase 中找出方法的返回类型?我正在使用 PostSharp 并尝试覆盖 CompileTimeValidate(MethodBase 方法)方法以确保该属性应用于具有正确签名的
我正在为try/catch语句创建一个简单的日志记录方法(没什么花哨的)。我要包括类名称和引发异常的方法。 有两种获取信息的方法。一种使用MethodBase.GetCurrentMethod()和异
我试图在运行时调用一个通用接口(interface)方法,但是在查找类型信息时它似乎找到了 IDomainEventSubscriber 而不是传递的正确类型。 抛出运行时错误:对象与目标类型不匹配。
我是一名优秀的程序员,十分优秀!