簡體   English   中英

PostSharp的LocationInterceptionAspect不適用於結構

[英]PostSharp's LocationInterceptionAspect doesn't work with structs

我做了一個BitsAspect來模擬C++位域,它采用這種方式:

[StructLayout(LayoutKind.Explicit)]
class Class {
    [FieldOffset(0)] public byte Whole;
    [FieldOffset(0)] [BitsAspect(0,0)] public byte Bit0;
    [FieldOffset(0)] [BitsAspect(1,1)] public byte Bit1;
}

它很好用,但僅適用於es class struct它不起作用:

[StructLayout(LayoutKind.Explicit)]
struct Struct {
    [FieldOffset(0)] public byte Whole;
    [FieldOffset(0)] [BitsAspect(0,0)] public byte Bit0;
    [FieldOffset(0)] [BitsAspect(0,1)] public byte Bit1;
}

這是測試:

[TestMethod]
public void BitOperations_Test() {
    var c = new Class();
    c.Bit1 = 1;
    Assert.AreEqual(2, c.Whole);
    Assert.AreEqual(1, c.Bit1);

    // all assertions pass to this point.

    var s = new Struct();
    s.Bit1 = 1;
    Assert.AreEqual(2, s.Whole); // fails: s.Whole is 1 :-(
    Assert.AreEqual(1, s.Bit1);
}

方面:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Property | MulticastTargets.Field)]
public class BitsAspect : LocationInterceptionAspect {
    private ulong _mask;
    private Type _type;
    public int BitOffset { get; private set; }
    public int BitsCount { get; private set; }

    public BitsAspect(int bitOffset, int bitsCount) {
        BitOffset = bitOffset;
        BitsCount = bitsCount;
    }

    public override void CompileTimeInitialize(LocationInfo targetLocation, AspectInfo aspectInfo) {
        _type = targetLocation.LocationType;
        if (_type.IsEnum) _type = _type.GetEnumUnderlyingType();
        ulong mask = ((ulong) 1 << BitsCount) - 1;
        _mask = mask << BitOffset;
        base.CompileTimeInitialize(targetLocation, aspectInfo);
    }

    public override void OnGetValue(LocationInterceptionArgs args) {
        var @this = args.Instance;
        var oldValue = Convert.ToUInt64(args.Binding.GetValue(ref @this, Arguments.Empty));
        var value = (oldValue & _mask) >> BitOffset;
        var converted = Convert.ChangeType(value, _type);
        args.Value = converted;
    }
    public override void OnSetValue(LocationInterceptionArgs args) {
        var @this = args.Instance;

        var newValue = Convert.ToUInt64(args.Value);
        var oldValue = Convert.ToUInt64(args.Binding.GetValue(ref @this, Arguments.Empty));

        var value = (oldValue & ~_mask) | (newValue << BitOffset);
        var converted = Convert.ChangeType(value, _type);
        args.SetNewValue(converted);
    }
}

我也可以使用value-type struct實現此目的嗎?

struct上的LocationInterceptionAspect應該可以正常工作了。

Bit1的聲明與Class有點不同:

[FieldOffset(0)] [BitsAspect(1,1)] public byte Bit1;

對於Struct:

[FieldOffset(0)] [BitsAspect(0,1)] public byte Bit1;

我敢打賭,這會有所作為。

當心可變的值類型,它們可能是純粹的邪惡

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM