PostSharp:删除/替换后台字段
本文关键字:后台 字段 替换 删除 PostSharp | 更新日期: 2023-09-27 18:08:04
我想知道PostSharp是否可以很容易地通过删除/替换后台字段来改变类的结构。
示例如下:
假设我有以下实体
class DataItem
{
public Int32 Id { get; set; }
public String Name { get; set; }
public Decimal? HourlyRateMon { get; set; }
public Decimal? HourlyRateTue { get; set; }
public Decimal? HourlyRateWed { get; set; }
public Decimal? HourlyRateThu { get; set; }
public Decimal? HourlyRateFri { get; set; }
}
将在64位上使用4 + 8 + 5*20 + 16字节的开销=每个实例128字节。
我想做的是应用一个方面,通过打包可空的小数来最小化对象的内存占用-就像
internal class DataItem
{
private CompactDecimal _hourlyRateFri;
private CompactDecimal _hourlyRateMon;
private CompactDecimal _hourlyRateThu;
private CompactDecimal _hourlyRateTue;
private CompactDecimal _hourlyRateWed;
public int Id { get; set; }
public string Name { get; set; }
public decimal? HourlyRateMon
{
get { return _hourlyRateMon; }
set { _hourlyRateMon = value; }
}
public decimal? HourlyRateTue
{
get { return _hourlyRateTue; }
set { _hourlyRateTue = value; }
}
public decimal? HourlyRateWed
{
get { return _hourlyRateWed; }
set { _hourlyRateWed = value; }
}
public decimal? HourlyRateThu
{
get { return _hourlyRateThu; }
set { _hourlyRateThu = value; }
}
public decimal? HourlyRateFri
{
get { return _hourlyRateFri; }
set { _hourlyRateFri = value; }
}
}
internal struct CompactDecimal
{
public uint Offset;
public static implicit operator decimal?(CompactDecimal d)
{
// here I can, for instance, go to a shared stream at the stream offset and read the decimal
}
public static implicit operator CompactDecimal(decimal? d)
{
// here I can, for instance, serialize the decimal to a shared stream and get the stream offset
}
}
将在64位上使用4 + 8 + 5*4 + 16字节的开销=每个实例48字节,每个实例节省80字节。如果我们需要存储数百万个实例,它可以节省大量内存。
我试图创建一个locationinterceptionaspectderived属性,但我没有得到预期的结果-不仅原来的后台字段仍然存在,而且我有10个实例的TestAttribute(5个属性,get/set为每个):
// Fields
[NonSerialized]
private TestAttribute <>z__aspect10;
[NonSerialized]
private TestAttribute <>z__aspect11;
[NonSerialized]
private TestAttribute <>z__aspect12;
[NonSerialized]
private TestAttribute <>z__aspect13;
[NonSerialized]
private TestAttribute <>z__aspect4;
[NonSerialized]
private TestAttribute <>z__aspect5;
[NonSerialized]
private TestAttribute <>z__aspect6;
[NonSerialized]
private TestAttribute <>z__aspect7;
[NonSerialized]
private TestAttribute <>z__aspect8;
[NonSerialized]
private TestAttribute <>z__aspect9;
private decimal? <HourlyRateFri>k__OriginalField;
private decimal? <HourlyRateMon>k__OriginalField;
private decimal? <HourlyRateThu>k__OriginalField;
private decimal? <HourlyRateTue>k__OriginalField;
private decimal? <HourlyRateWed>k__OriginalField;
要么是我做错了什么,要么是PostSharp不支持我想要实现的目标。
TestAttribute现在不做任何事情-
[Serializable]
public class TestAttribute : LocationInterceptionAspect, IInstanceScopedAspect
{
public override void CompileTimeInitialize(LocationInfo targetLocation, AspectInfo aspectInfo)
{
//base.CompileTimeInitialize(targetLocation, aspectInfo);
}
#region <<< Public methods >>>
public Object CreateInstance(AdviceArgs adviceArgs)
{
return MemberwiseClone();
}
public override void OnGetValue(LocationInterceptionArgs args)
{
//args.
//base.OnGetValue(args);
}
public override void OnSetValue(LocationInterceptionArgs args)
{
//base.OnSetValue(args);
}
public void RuntimeInitializeInstance()
{
}
#endregion
}
首先,您还需要计算流本身使用的内存。基本上,您只需将Nullable中的bool替换为int索引,从而不节省任何内容。另外,请注意,在64位机器上,内存填充为8字节,因此decimal?
有24字节大。
节省内存的方法是将可空类型的bool打包到位图中。但是,您需要引入一个字段并更改后备字段的类型。PostSharp Aspect Framework不支持这个
另一种方法是不要使属性自动,并使用使用引入的接口获取或设置值的方面来重写getter和setter。然而,在这种情况下,您需要每个实例有2个对象——实例级aspect对象,具有位图和十进制数组来保存值。这将产生这样的开销:只有在一个类中使用了8个可空值之后,才会节省内存。
一个小小的改进是有一个公共基类,它将包含数组和位图。您将不再需要实例级方面,只需将十进制数组和位图保存在基类字段中。