1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

FieldInfo SetValue/GetValue with Variant support

This commit is contained in:
Brian Fiete 2020-09-05 06:02:13 -07:00
parent 8591172bb2
commit e37e1ac687
2 changed files with 221 additions and 29 deletions

View file

@ -106,7 +106,7 @@ namespace System.Reflection
return .Ok;
}
public Result<void> SetValue(Object obj, Variant value)
public Result<void, Error> SetValue(Object obj, Variant value)
{
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
if (mTypeInstance.IsStruct)
@ -124,7 +124,7 @@ namespace System.Reflection
}
}
if (!typeMatched)
return .Err;//("Invalid target type");
return .Err(.InvalidTargetType);
}
dataAddr = (void*)((int)dataAddr + mFieldData.mData);
@ -140,7 +140,94 @@ namespace System.Reflection
return .Ok;
}
else
return .Err;//("Invalid type");
return .Err(.InvalidValueType);
}
value.CopyValueData(dataAddr);
return .Ok;
}
public Result<void, Error> SetValue(Variant target, Object value)
{
var target;
var targetType = target.VariantType;
void* dataAddr = target.DataPtr;
if (targetType != mTypeInstance)
{
if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance)))
return .Err(.InvalidTargetType); // Invalid target type
dataAddr = target.Get<void*>();
}
dataAddr = (void*)((int)dataAddr + mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
if (value == null)
{
if ((fieldType.IsValueType) && (!fieldType.IsPointer))
{
return .Err(.InvalidValueType);
}
else
{
*((int*)dataAddr) = 0;
return .Ok;
}
}
Type rawValueType = value.[Friend]RawGetType();
void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset;
if (rawValueType.IsBoxedStructPtr)
valueDataAddr = *(void**)valueDataAddr;
Type valueType = value.GetType();
if ((valueType != fieldType) && (valueType.IsTypedPrimitive))
valueType = valueType.UnderlyingType;
if (valueType == fieldType)
{
if (valueType.IsObject)
*((void**)dataAddr) = Internal.UnsafeCastToPtr(value);
else
Internal.MemCpy(dataAddr, valueDataAddr, fieldType.[Friend]mSize);
}
else
{
return .Err(.InvalidValueType);
}
return .Ok;
}
public Result<void, Error> SetValue(Variant target, Variant value)
{
var target;
var targetType = target.VariantType;
void* dataAddr = target.DataPtr;
if (targetType != mTypeInstance)
{
if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance)))
return .Err(.InvalidTargetType);
dataAddr = target.Get<void*>();
}
dataAddr = (void*)((int)dataAddr + mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
let variantType = value.VariantType;
if (variantType != fieldType)
{
if ((variantType.IsPointer) && (variantType.UnderlyingType == fieldType))
{
void* srcPtr = value.Get<void*>();
Internal.MemCpy(dataAddr, srcPtr, fieldType.Size);
return .Ok;
}
else
return .Err(.InvalidValueType);
}
value.CopyValueData(dataAddr);
@ -161,9 +248,6 @@ namespace System.Reflection
void* GetDataPtrAndType(Object value, out Type type)
{
type = value.[Friend]RawGetType();
/*if (type.IsStruct)
return &value;*/
if (type.IsBoxedStructPtr)
return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset);
if (type.IsBoxed)
@ -171,7 +255,7 @@ namespace System.Reflection
return ((uint8*)Internal.UnsafeCastToPtr(value));
}
public Result<void> GetValue<TMember>(Object target, out TMember value)
public Result<void, Error> GetValue<TMember>(Object target, out TMember value)
{
value = default(TMember);
@ -181,11 +265,11 @@ namespace System.Reflection
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
// Unhandled
return .Err;
return .Err(.InvalidTargetType);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return .Err(.InvalidTargetType);
targetDataAddr = null;
}
@ -195,7 +279,7 @@ namespace System.Reflection
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //"Invalid type");
return .Err(.InvalidTargetType); //"Invalid type");
}
Type tMember = typeof(TMember);
@ -214,18 +298,18 @@ namespace System.Reflection
}
else
{
return .Err;
return .Err(.InvalidValueType);
}
return .Ok;
}
public Result<Variant> GetValue(Object target)
Result<Variant> GetValue(void* startTargetDataAddr, Type tTarget)
{
Variant value = Variant();
void* targetDataAddr;
if (target == null)
void* targetDataAddr = startTargetDataAddr;
if (targetDataAddr == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
@ -234,14 +318,9 @@ namespace System.Reflection
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
targetDataAddr = null;
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type;
}
@ -254,11 +333,11 @@ namespace System.Reflection
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
if (typeCode == TypeCode.Object)
{
if (typeCode == TypeCode.Object)
{
value.[Friend]mStructType = 0;
value.[Friend]mData = *(int*)targetDataAddr;
}
value.[Friend]mData = *(int*)targetDataAddr;
}
else
{
value = Variant.Create(fieldType, targetDataAddr);
@ -267,12 +346,12 @@ namespace System.Reflection
return value;
}
public Result<Variant> GetValueReference(Object target)
public Result<Variant> GetValueReference(void* startTargetDataAddr, Type tTarget)
{
Variant value = Variant();
void* targetDataAddr;
if (target == null)
void* targetDataAddr = startTargetDataAddr;
if (targetDataAddr == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
@ -286,9 +365,6 @@ namespace System.Reflection
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type;
}
@ -306,6 +382,94 @@ namespace System.Reflection
return value;
}
public Result<Variant> GetValue(Object target)
{
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValue(null, null);
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
return GetValue(targetDataAddr, tTarget);
}
}
public Result<Variant> GetValue(Variant target)
{
if (!target.HasValue)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValue(null, null);
}
else
{
var target;
return GetValue(target.DataPtr, target.VariantType);
}
}
public Result<Variant> GetValueReference(Object target)
{
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference(null, null);
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
return GetValueReference(targetDataAddr, tTarget);
}
}
public Result<Variant> GetValueReference(Variant target)
{
if (!target.HasValue)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference(null, null);
}
else
{
var target;
return GetValueReference(target.DataPtr, target.VariantType);
}
}
public struct Enumerator : IEnumerator<FieldInfo>
{
BindingFlags mBindingFlags;

View file

@ -494,6 +494,9 @@ namespace Tests
sb.mB = "Struct B";
sb.mC = .() { mA = 1.2f, mB = 2.3f };
Variant sbVariant = .Create(sb);
defer sbVariant.Dispose();
let type = sb.GetType() as TypeInstance;
let fields = type.GetFields();
int fieldIdx = 0;
@ -501,8 +504,13 @@ namespace Tests
{
var fieldVal = field.GetValue(sb).Value;
defer fieldVal.Dispose();
var fieldVal2 = field.GetValue(&sb).Value;
defer fieldVal2.Dispose();
var fieldVal3 = field.GetValue(sbVariant).Value;
defer fieldVal3.Dispose();
switch (fieldIdx)
{
case 0:
@ -514,6 +522,26 @@ namespace Tests
Test.Assert(fieldVal2.Get<int>() == 25);
field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32);
Test.Assert(fieldVal3.Get<int>() == 25);
field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32);
field.SetValue(sbVariant, 34);
fieldVal3.Dispose();
fieldVal3 = field.GetValue(sbVariant).Value;
Test.Assert(fieldVal3.Get<int>() == 34);
Variant varInt = .Create(45);
field.SetValue(sbVariant, varInt);
fieldVal3.Dispose();
fieldVal3 = field.GetValue(sbVariant).Value;
Test.Assert(fieldVal3.Get<int>() == 45);
field.SetValue(&sb, varInt);
fieldVal2.Dispose();
fieldVal2 = field.GetValue(&sb).Value;
Test.Assert(fieldVal2.Get<int>() == 45);
case 1:
Test.Assert(fieldVal.Get<String>() === "Struct B");
field.SetValue(&sb, "Struct C");