2015-08-14 47 views
1

我想通過刪除/替換後臺字段來找到PostSharp是否可以很容易地用於更改類的結構。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; } 
} 

將使用4 + 8 + 5 * 20 + 16個字節的開銷上每64位= 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 
    } 
} 

將使用4個+ 8個+ 5個* 4個+ 16個字節64位的開銷=每個實例48字節,節省80字節/實例。如果我們需要存儲數百萬個實例,它會爲我們節省大量內存。

我試着創建一個LocationInterceptionAspect派生的屬性,但我沒有得到預期的結果 - 不僅原始支持字段仍然存在,但我也有10個TestAttribute實例(5個屬性,每個獲取/設置):

// 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 
} 

任何幫助表示讚賞。

回答

0

首先,您還需要計算流自身使用的內存。基本上你只要用uint索引替換Nullable中的bool,從而不需要任何東西。此外請注意,在64位機器上,內存填充爲8個字節,因此decimal?爲24個字節。

保存內存的方法是將bools從可空類型打包到位圖中。但是,您需要引入一個字段並更改支持字段的類型。 PostSharp Aspect框架不支持這一點。

其他的方法是不使屬性自動和覆蓋getter和setter使用一個方面,將獲得或設置值使用一個介紹的接口。但是在這種情況下,您需要爲每個實例增加2個對象 - 帶有位圖和小數數組的實例級別的aspect對象以保存值。這會產生這樣的開銷,只有在類中使用8個可爲空的值後纔會保存內存。

稍有改進就是擁有一個具有數組和位圖的通用基類。您不再需要實例級別的方面,只需將基本類字段中保存的十進制數組和位圖即可。這個方法會將內存從5個可空值中保存起來。