2015-05-12 61 views
0

工作,我做了一個BitsAspect模擬C++位字段,其應用是這樣的:PostSharp的LocationInterceptionAspect不與結構

[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; 
} 

它的偉大工程,但僅限於class ES。在struct的IT只是不工作:

[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); 
    } 
} 

什麼辦法可以與價值型實現這一struct也是?

回答

1

LocationInterceptionAspect結構應該在這裏沒有任何問題。

位1的宣言類有一點不同:

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

和結構:

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

我敢打賭,它使其中的差別。

注意可變值類型,它們可以是pure evil

+0

d'oh!太尷尬了...... – Tar