internal static void Construct <TDstContainer, TSrcContainer>( ref TDstContainer dstContainer, ref TSrcContainer srcContainer, VisitResult result, PropertyContainerConstructOptions options = default) { if (RuntimeTypeInfoCache <TDstContainer> .IsAbstractOrInterface() || typeof(TDstContainer) != dstContainer.GetType()) { var propertyBag = PropertyBagResolver.Resolve(dstContainer.GetType()); var action = new ConstructAbstractType <TSrcContainer> { Options = options, Result = result, SrcContainer = srcContainer, DstContainerBoxed = dstContainer }; propertyBag.Cast(ref action); dstContainer = (TDstContainer)action.DstContainerBoxed; } else { var visitor = new TypeConstructionVisitor <TDstContainer>(dstContainer, result, options); Visit(ref srcContainer, ref visitor); dstContainer = visitor.Target; } }
static ContainerPropertyBag() { if (!RuntimeTypeInfoCache.IsContainerType(typeof(TContainer))) { throw new InvalidOperationException($"Failed to create a property bag for Type=[{typeof(TContainer)}]. The type is not a valid container type."); } }
public static VisitResult Construct <TDstContainer, TSrcContainer>(ref TDstContainer dstContainer, ref TSrcContainer srcContainer, PropertyContainerConstructOptions options = default) { if (!RuntimeTypeInfoCache <TSrcContainer> .IsValueType() && srcContainer == null) { throw new ArgumentNullException(nameof(srcContainer)); } if (!RuntimeTypeInfoCache <TDstContainer> .IsValueType() && dstContainer == null) { if (typeof(UnityEngine.Object).IsAssignableFrom(typeof(TDstContainer))) { throw new ArgumentNullException(nameof(dstContainer)); } if (!TypeConstruction.TryConstruct(srcContainer.GetType(), out dstContainer)) { throw new ArgumentNullException(nameof(dstContainer)); } } var result = VisitResult.GetPooled(); Construct(ref dstContainer, ref srcContainer, result, options); return(result); }
public void VisitProperty <TDstElementProperty, TDstElementValue>( TDstElementProperty dstElementProperty, ref TDstContainer dstContainer, ref ChangeTracker changeTracker) where TDstElementProperty : ICollectionElementProperty <TDstContainer, TDstElementValue> { if (!dstElementProperty.IsContainer) { return; } if (!RuntimeTypeInfoCache <TSrcElementValue> .IsValueType() && null == SrcElementValue) { dstElementProperty.SetValue(ref dstContainer, default); return; } var dstValue = dstElementProperty.GetValue(ref dstContainer); if (!RuntimeTypeInfoCache <TDstElementValue> .IsValueType() && null == dstValue || SrcElementValue is TDstElementValue && dstValue.GetType() != SrcElementValue.GetType()) { if (!TypeConstructionUtility.TryConstructFromData(ref SrcElementValue, Options.TypeIdentifierKey, Result, out dstValue)) { return; } } PropertyContainer.Construct(ref dstValue, ref SrcElementValue, Result, Options); dstElementProperty.SetValue(ref dstContainer, dstValue); }
public void VisitProperty <TDstElementProperty, TDstElementValue>( TDstElementProperty dstElementProperty, ref TDstContainer dstContainer, ref ChangeTracker changeTracker) where TDstElementProperty : ICollectionElementProperty <TDstContainer, TDstElementValue> { if (dstElementProperty.IsReadOnly) { return; } if (!RuntimeTypeInfoCache <TSrcElementValue> .IsValueType() && null == SrcElementValue) { dstElementProperty.SetValue(ref dstContainer, default); } else if (TypeConversion.TryConvert <TSrcElementValue, TDstElementValue>(SrcElementValue, out var dstElementValue)) { dstElementProperty.SetValue(ref dstContainer, dstElementValue); } else if (dstElementProperty.IsContainer) { dstElementValue = dstElementProperty.GetValue(ref dstContainer); if (RuntimeTypeInfoCache <TDstElementValue> .IsValueType() || null != dstElementValue) { Transfer(ref dstElementValue, ref SrcElementValue, Result); } dstElementProperty.SetValue(ref dstContainer, dstElementValue); } else { Result.AddLog($"PropertyContainer.Transfer ContainerType=[{typeof(TDstContainer)}] PropertyName=[{dstElementProperty.GetName()}] could not be transferred."); } }
public void VisitCollectionProperty <TDstProperty, TDstValue>( TDstProperty dstProperty, ref TDstContainer dstContainer, ref ChangeTracker changeTracker) where TDstProperty : ICollectionProperty <TDstContainer, TDstValue> { if (!RuntimeTypeInfoCache <TSrcValue> .IsValueType() && null == SrcValue) { dstProperty.SetValue(ref dstContainer, default); return; } var dstValue = dstProperty.GetValue(ref dstContainer); if (!RuntimeTypeInfoCache <TDstValue> .IsValueType() && null == dstValue) { if (typeof(UnityEngine.Object).IsAssignableFrom(typeof(TDstValue))) { return; } if (TypeConstruction.TryConstruct(SrcValue.GetType(), out dstValue)) { dstProperty.SetValue(ref dstContainer, dstValue); } else if (TypeConstruction.TryConstruct(out dstValue)) { dstProperty.SetValue(ref dstContainer, dstValue); } else if (typeof(TDstValue).IsArray) { dstValue = (TDstValue)Activator.CreateInstance(typeof(TDstValue), SrcProperty.GetCount(ref SrcContainer)); dstProperty.SetValue(ref dstContainer, dstValue); } } var srcCount = SrcProperty.GetCount(ref SrcContainer); var dstCount = dstProperty.GetCount(ref dstContainer); if (srcCount != dstCount) { dstProperty.SetCount(ref dstContainer, srcCount); } for (var i = 0; i < srcCount; i++) { var action = new SrcCollectionElementGetter <TDstProperty, TDstValue> { Options = Options, Result = Result, DstProperty = dstProperty, DstContainer = dstContainer, Index = i }; SrcProperty.GetPropertyAtIndex(ref SrcContainer, i, ref changeTracker, ref action); dstContainer = action.DstContainer; } }
public CollectionElementProperty(ArrayProperty <TContainer, TElement> property, int index, IPropertyAttributeCollection attributes = null) { m_Property = property; IsContainer = RuntimeTypeInfoCache <TElement> .IsContainerType(); Attributes = attributes; Index = index; }
/// <summary> /// Initializes a new instance of the <see cref="GeneratePropertyBagsForTypeAttribute"/> attribute. /// </summary> /// <param name="type">The type to generate a property bag for.</param> /// <exception cref="ArgumentException">The specified type is not a valid container type.</exception> public GeneratePropertyBagsForTypeAttribute(Type type) { if (!RuntimeTypeInfoCache.IsContainerType(type)) { throw new ArgumentException($"{type.Name} is not a valid container type."); } Type = type; }
/// <summary> /// Tries to visit the specified <paramref name="container"/> by ref using the specified <paramref name="visitor"/>. /// </summary> /// <param name="visitor">The visitor.</param> /// <param name="container">The container to visit.</param> /// <param name="errorCode">When this method returns, contains the error code.</param> /// <typeparam name="TContainer">The declared container type.</typeparam> /// <returns><see langword="true"/> if the visitation succeeded; <see langword="false"/> otherwise.</returns> public static bool TryAccept <TContainer>(IPropertyBagVisitor visitor, ref TContainer container, out VisitErrorCode errorCode) { if (!RuntimeTypeInfoCache <TContainer> .IsContainerType) { errorCode = VisitErrorCode.InvalidContainerType; return(false); } // Can not visit a null container. if (RuntimeTypeInfoCache <TContainer> .CanBeNull) { if (EqualityComparer <TContainer> .Default.Equals(container, default)) { errorCode = VisitErrorCode.NullContainer; return(false); } } if (!RuntimeTypeInfoCache <TContainer> .IsValueType && typeof(TContainer) != container.GetType()) { if (!RuntimeTypeInfoCache.IsContainerType(container.GetType())) { errorCode = VisitErrorCode.InvalidContainerType; return(false); } var properties = PropertyBagStore.GetPropertyBag(container.GetType()); if (null == properties) { errorCode = VisitErrorCode.MissingPropertyBag; return(false); } // At this point the generic parameter is useless to us since it's not the correct type. // Instead we need to retrieve the untyped property bag and accept on that. Since we don't know the type // We need to box the container and let the property bag cast it internally. var boxed = (object)container; properties.Accept(visitor, ref boxed); container = (TContainer)boxed; } else { var properties = PropertyBagStore.GetPropertyBag <TContainer>(); if (null == properties) { errorCode = VisitErrorCode.MissingPropertyBag; return(false); } PropertyBag.AcceptWithSpecializedVisitor(properties, visitor, ref container); } errorCode = VisitErrorCode.Ok; return(true); }
public static void Transfer <TDestination, TSource>(ref TDestination destination, ref TSource source, ref ChangeTracker changeTracker) { if (!RuntimeTypeInfoCache <TDestination> .IsValueType() && destination == null) { throw new ArgumentNullException(nameof(destination)); } DoTransfer(ref destination, ref source, ref changeTracker); }
public UnmanagedProperty(string name, int offset, bool readOnly = false, IPropertyAttributeCollection attributes = null) { m_Name = name; Offset = offset; IsReadOnly = readOnly; IsContainer = RuntimeTypeInfoCache <TValue> .IsContainerType(); Attributes = attributes; }
public ListProperty(string name, Getter getter, Setter setter, IPropertyAttributeCollection attributes = null) { m_Name = name; m_Getter = getter; m_Setter = setter; m_Attributes = attributes; if (RuntimeTypeInfoCache <TElement> .IsArray()) { throw new Exception("ArrayProperty`2 does not support array of array"); } }
public static VisitResult Transfer <TDstContainer, TSrcContainer>(ref TDstContainer dstContainer, ref TSrcContainer srcContainer) { if (!RuntimeTypeInfoCache <TDstContainer> .IsValueType() && dstContainer == null) { throw new ArgumentNullException(nameof(dstContainer)); } var result = VisitResult.GetPooled(); Transfer(ref dstContainer, ref srcContainer, result); return(result); }
public void VisitCollectionProperty <TDstProperty, TDstValue>( TDstProperty dstProperty, ref TDstContainer dstContainer, ref ChangeTracker changeTracker) where TDstProperty : ICollectionProperty <TDstContainer, TDstValue> { if (dstProperty.IsReadOnly) { return; } var dstValue = dstProperty.GetValue(ref dstContainer); if (!RuntimeTypeInfoCache <TSrcValue> .IsValueType() && null == SrcValue) { dstProperty.SetValue(ref dstContainer, default); } else if (RuntimeTypeInfoCache <TSrcValue> .IsValueType() || null != dstValue) { var srcCount = SrcProperty.GetCount(ref SrcContainer); var dstCount = dstProperty.GetCount(ref dstContainer); if (srcCount != dstCount) { dstProperty.SetCount(ref dstContainer, srcCount); } for (var i = 0; i < srcCount; i++) { var action = new SrcCollectionElementGetter <TDstProperty, TDstValue> { Result = Result, DstProperty = dstProperty, DstContainer = dstContainer, Index = i }; SrcProperty.GetPropertyAtIndex(ref SrcContainer, i, ref changeTracker, ref action); dstContainer = action.DstContainer; } } else { Result.AddLog($"PropertyContainer.Transfer ContainerType=[{typeof(TDstContainer)}] PropertyName=[{dstProperty.GetName()}] could not be transferred."); } }
static void DoTransfer <TDestination, TSource>(ref TDestination destination, ref TSource source, ref ChangeTracker changeTracker) { if (RuntimeTypeInfoCache <TSource> .IsAbstractOrInterface() || typeof(TSource) != source.GetType()) { var propertyBag = PropertyBagResolver.Resolve(source.GetType()); var action = new TransferAbstractType <TDestination> { Destination = destination, SourceContainer = source }; propertyBag.Cast(ref action); destination = action.Destination; } else { Visit(ref destination, new TransferVisitor <TSource>(source), ref changeTracker); } }
static void Transfer <TDstContainer, TSrcContainer>( ref TDstContainer dstContainer, ref TSrcContainer srcContainer, VisitResult result) { if (RuntimeTypeInfoCache <TDstContainer> .IsAbstractOrInterface() || typeof(TDstContainer) != dstContainer.GetType()) { var propertyBag = PropertyBagResolver.Resolve(dstContainer.GetType()); var action = new TransferAbstractType <TSrcContainer> { Result = result, SrcContainer = srcContainer, DstContainerBoxed = dstContainer }; propertyBag.Cast(ref action); dstContainer = (TDstContainer)action.DstContainerBoxed; } else { var visitor = new TransferVisitor <TDstContainer>(dstContainer, result); Visit(ref srcContainer, ref visitor); dstContainer = visitor.Target; } }