/// <summary> /// Get all optional components from <see cref="BuildConfiguration"/>, that matches <see cref="Type"/>. /// Optional component types not found in <see cref="BuildConfiguration"/> will be set to a new instance of that type. /// </summary> /// <param name="context">The <see cref="BuildContext"/> used by the execution of this <see cref="BuildStep"/>.</param> /// <param name="type">Type of the components.</param> /// <returns>List of optional components.</returns> public IEnumerable <IBuildComponent> GetOptionalComponents(BuildContext context, Type type) { CheckTypeAndThrowIfInvalid <IBuildComponent>(type); if (OptionalComponents == null || !OptionalComponents.Contains(type)) { throw new InvalidOperationException($"Component type '{type.FullName}' is not in the {nameof(OptionalComponents)} list."); } var lookup = new Dictionary <Type, IBuildComponent>(); foreach (var optionalComponentType in OptionalComponents) { if (!type.IsAssignableFrom(optionalComponentType)) { continue; } if (!context.BuildConfiguration.TryGetComponent(optionalComponentType, out var component)) { component = TypeConstruction.Construct <IBuildComponent>(optionalComponentType); } lookup[optionalComponentType] = component; } return(lookup.Values); }
public void ReturnsAnActualInstanceTests() { { var instance = TypeConstruction.Construct <ConstructibleBaseType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance.Value, Is.EqualTo(25.0f)); } { var instance = TypeConstruction.Construct <ConstructibleDerivedType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance.Value, Is.EqualTo(25.0f)); Assert.That(instance.SubValue, Is.EqualTo(50.0f)); } { var instance = TypeConstruction.Construct <ConstructibleDerivedType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance.Value, Is.EqualTo(25.0f)); Assert.That(instance.SubValue, Is.EqualTo(50.0f)); } { var instance = TypeConstruction.Construct <ScriptableObjectType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance, Is.Not.False); } }
public void ConstructionOfInvalidTypeThrows() { Assert.Throws <InvalidOperationException>(() => TypeConstruction.Construct <IConstructInterface>()); Assert.Throws <InvalidOperationException>(() => TypeConstruction.Construct <AbstractConstructibleBaseType>()); Assert.Throws <InvalidOperationException>(() => TypeConstruction.Construct <NonConstructibleDerivedType>()); Assert.Throws <InvalidOperationException>(() => TypeConstruction.Construct <ParameterConstructorType>()); }
static void AssertPropertyIsOfType <TContainer, TValue>(IPropertyBag <TContainer> propertyBag, string propertyName) { var container = TypeConstruction.Construct <TContainer>(typeof(TContainer)); var changeTracker = default(ChangeTracker); var action = new AssertThatPropertyIsOfType <TContainer, TValue>(); Assert.That(propertyBag.FindProperty(propertyName, ref container, ref changeTracker, ref action), Is.True); }
static T CopyComponent <T>(T value) { var result = TypeConstruction.Construct <T>(value.GetType()); PropertyContainer.Construct(ref result, ref value).Dispose(); PropertyContainer.Transfer(ref result, ref value).Dispose(); return(result); }
public VisitStatus Visit <TContainer, TValue>(Property <TContainer, TValue> property, ref TContainer container, ref TValue value) { if (!RuntimeTypeInfoCache <TValue> .CanBeNull || null != value) { return(VisitStatus.Unhandled); } if (typeof(UnityEngine.Object).IsAssignableFrom(typeof(TValue))) { return(VisitStatus.Unhandled); } if (!property.IsReadOnly && property.HasAttribute <CreateInstanceOnInspectionAttribute>() && !(property is ICollectionElementProperty)) { var attribute = property.GetAttribute <CreateInstanceOnInspectionAttribute>(); if (null == attribute.Type) { if (TypeConstruction.CanBeConstructed <TValue>()) { value = TypeConstruction.Construct <TValue>(); property.SetValue(ref container, value); return(VisitStatus.Unhandled); } Debug.LogWarning(PropertyChecks.GetNotConstructableWarningMessage(typeof(TValue))); } else { var isAssignable = typeof(TValue).IsAssignableFrom(attribute.Type); var isConstructable = TypeConstruction.GetAllConstructableTypes(typeof(TValue)) .Contains(attribute.Type); if (isAssignable && isConstructable) { value = TypeConstruction.Construct <TValue>(attribute.Type); property.SetValue(ref container, value); return(VisitStatus.Unhandled); } Debug.LogWarning(isAssignable ? PropertyChecks.GetNotConstructableWarningMessage(attribute.Type) : PropertyChecks.GetNotAssignableWarningMessage(attribute.Type, typeof(TValue))); } } Visitor.AddToPath(property); try { var path = Visitor.GetCurrentPath(); var element = new NullElement <TValue>(VisitorContext.Root, property, path); VisitorContext.Parent.contentContainer.Add(element); } finally { Visitor.RemoveFromPath(property); } return(VisitStatus.Stop); }
/// <summary> /// Get the value of a <see cref="Type"/> component if found. /// Otherwise an instance created using <see cref="TypeConstruction"/> utility. /// The container is not modified. /// </summary> /// <param name="type"><see cref="Type"/> of the component.</param> /// <returns>The component value.</returns> public TComponent GetComponentOrDefault(Type type) { CheckComponentTypeAndThrowIfInvalid(type); if (!TryGetComponent(type, out var value)) { return(TypeConstruction.Construct <TComponent>(type)); } return(value); }
internal static TComponent Construct(Type componentType) { if (!TypeConstruction.CanBeConstructed(componentType)) { throw new InvalidOperationException($"Component type {componentType.FullName} cannot be constructed because it does not have a default, implicit or registered constructor."); } return(TypeConstruction.Construct <TComponent>(componentType)); }
static void AssertPropertyValueAndTypeIsEqualTo <TContainer>(IPropertyBag <TContainer> propertyBag, string propertyName, object expectedValue) { var container = TypeConstruction.Construct <TContainer>(typeof(TContainer)); var changeTracker = default(ChangeTracker); var action = new AssertThatPropertyValueAndTypeIsEqualTo <TContainer> { ExpectedValue = expectedValue }; Assert.That(propertyBag.FindProperty(propertyName, ref container, ref changeTracker, ref action), Is.True); }
/// <summary> /// Set the value of a <see cref="Type"/> component on this container using an instance created using <see cref="TypeConstruction"/> utility. /// </summary> /// <param name="type">Type of the component.</param> public void SetComponent(Type type) { CheckComponentTypeAndThrowIfInvalid(type); if (type.IsInterface || type.IsAbstract) { throw new InvalidOperationException($"{nameof(type)} cannot be interface or abstract."); } SetComponent(type, TypeConstruction.Construct <TComponent>(type)); }
public static IEnumerable <T> ConstructTypesDerivedFrom <T>(bool fromUnityAssembliesOnly = true) { var types = TypeCache.GetTypesDerivedFrom <T>().Where(type => !type.IsAbstract && !type.IsGenericType); if (fromUnityAssembliesOnly) { types = types.Where(type => type.Assembly.GetName().Name.StartsWith("Unity.")); } return(types.Select(type => TypeConstruction.Construct <T>(type))); }
public static T ConstructFromAssemblyQualifiedTypeName <T>(string assemblyQualifiedTypeName) { var type = Type.GetType(assemblyQualifiedTypeName); if (null == type && FormerNameAttribute.TryGetCurrentTypeName(assemblyQualifiedTypeName, out var currentTypeName)) { type = Type.GetType(currentTypeName); } return(TypeConstruction.Construct <T>(type)); }
/// <summary> /// Get the first build artifact value that is assignable to specified type, or create and set it if not found. /// Multiple build artifact value can be stored per build configuration. /// </summary> /// <typeparam name="T">The build artifact type.</typeparam> /// <returns>The build artifact value.</returns> public T GetOrCreateBuildArtifact <T>() where T : class, IBuildArtifact, new() { var artifact = GetBuildArtifact <T>(); if (artifact == null) { artifact = TypeConstruction.Construct <T>(); SetBuildArtifact(artifact); } return(artifact); }
/// <summary> /// Get value of type <typeparamref name="T"/> if found, otherwise a new instance of type <typeparamref name="T"/> constructed with <see cref="TypeConstruction"/>. /// </summary> /// <typeparam name="T">The value type.</typeparam> /// <returns>The value or new instance of type <typeparamref name="T"/>.</returns> public T GetOrCreateValue <T>() where T : class { var value = GetValue <T>(); if (value == null) { value = TypeConstruction.Construct <T>(); SetValue(value); } return(value); }
public void ConstructingAnInstance_WithAConstructableType_ReturnsAnActualInstance() { Assert.That(TypeConstruction.Construct <Types.NoConstructorClass>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.NoConstructorStruct>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.DefaultConstructorClass>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.DefaultAndCustomConstructorClass>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.CustomConstructorStruct>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.ChildOfAbstractClassWithNoConstructor>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.ChildOfAbstractClassWithDefaultConstructor>(), Is.Not.Null); Assert.That(TypeConstruction.Construct <Types.ChildOfAbstractClassWithPrivateDefaultConstructor>(), Is.Not.Null); }
/// <summary> /// Get the first build artifact value that is assignable to specified type, or create and set it if not found. /// Multiple build artifact value can be stored per build configuration. /// </summary> /// <param name="buildArtifactType">The build artifact type.</param> /// <returns>The build artifact value.</returns> public IBuildArtifact GetOrCreateBuildArtifact(Type buildArtifactType) { BuildArtifacts.ValidateBuildArtifactTypeAndThrow(buildArtifactType); var artifact = GetBuildArtifact(buildArtifactType); if (artifact == null) { artifact = TypeConstruction.Construct <IBuildArtifact>(buildArtifactType); SetBuildArtifact(artifact); } return(artifact); }
/// <summary> /// Construct instance of first type derived from <typeparamref name="T"/> that satisfies the filtering function. /// Derived type must have an implicit, default or registered constructor. /// </summary> /// <typeparam name="T">The derived type.</typeparam> /// <param name="filter">The filtering function.</param> /// <param name="value">New instance of derived type.</param> /// <returns><see langword="true"/> if new instance was successfully constructed, <see langword="false"/> otherwise.</returns> public static bool TryConstructTypeDerivedFrom <T>(Func <Type, bool> filter, out T value) { var types = GetConstructibleTypesDerivedFrom <T>(filter); if (!types.Any()) { value = default; return(false); } value = TypeConstruction.Construct <T>(types.FirstOrDefault()); return(true); }
/// <summary> /// Get value of type <typeparamref name="T"/> if found. /// Otherwise a new instance of type <typeparamref name="T"/> constructed using <see cref="TypeConstruction"/> utility and then set on this build context. /// </summary> /// <typeparam name="T">The value type.</typeparam> /// <returns>The value or new instance of type <typeparamref name="T"/>.</returns> public T GetOrCreateValue <T>() where T : class { ValidateValueTypeAndThrow(typeof(T)); var value = GetValue <T>(); if (value == null) { value = TypeConstruction.Construct <T>(); SetValue(value); } return(value); }
public void CanSetExplicitConstruction() { Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.False); TypeConstruction.SetExplicitConstructionMethod(ExplicitConstruction); Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.True); { var instance = TypeConstruction.Construct <ParameterConstructorType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance.Value, Is.EqualTo(10.0f)); } TypeConstruction.UnsetExplicitConstructionMethod(ExplicitConstruction); Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.False); }
internal static IBuildStep CreateStepFromType(Type type) { if (type == null) { throw new NullReferenceException(nameof(type)); } if (!typeof(IBuildStep).IsAssignableFrom(type)) { Debug.LogError($"Build step type '{type.FullName}' does not derive from {nameof(IBuildStep)}."); return(null); } return(TypeConstruction.Construct <IBuildStep>(type)); }
/// <summary> /// Get the value of an optional <see cref="Type"/> component from <see cref="BuildConfiguration"/>. /// The component <see cref="Type"/> must exist in the <see cref="OptionalComponents"/> list. /// If the component is not found in <see cref="BuildConfiguration"/>, a new instance of type <see cref="Type"/> is returned. /// </summary> /// <param name="context">The <see cref="BuildContext"/> used by the execution of this <see cref="BuildStep"/>.</param> /// <param name="type">Type of the optional component.</param> /// <returns>The value of the optional component.</returns> public IBuildComponent GetOptionalComponent(BuildContext context, Type type) { CheckTypeAndThrowIfInvalid <IBuildComponent>(type); if (OptionalComponents == null || !OptionalComponents.Contains(type)) { throw new InvalidOperationException($"Component type '{type.FullName}' is not in the {nameof(OptionalComponents)} list."); } if (context.BuildConfiguration.HasComponent(type)) { return(context.BuildConfiguration.GetComponent(type)); } return(TypeConstruction.Construct <IBuildComponent>(type)); }
public static T ConstructFromAssemblyQualifiedTypeName <T>(string assemblyQualifiedTypeName) { if (string.IsNullOrEmpty(assemblyQualifiedTypeName)) { throw new ArgumentException(nameof(assemblyQualifiedTypeName)); } var type = Type.GetType(assemblyQualifiedTypeName); if (null == type && FormerNameAttribute.TryGetCurrentTypeName(assemblyQualifiedTypeName, out var currentTypeName)) { type = Type.GetType(currentTypeName); } return(TypeConstruction.Construct <T>(type)); }
void OnCreateItem(ChangeEvent <Type> evt) { var type = evt.newValue; if (type == typeof(Null)) { return; } var instance = type == typeof(T) ? TypeConstruction.Construct <T>() : TypeConstruction.Construct <T>(type); ReloadWithInstance(instance); }
/// <summary> /// Try to get the value of a <see cref="Type"/> component. /// </summary> /// <param name="type"><see cref="Type"/> of the component.</param> /// <param name="value">Out value of the component.</param> public bool TryGetComponent(Type type, out TComponent value) { if (!TryGetDerivedTypeFromBaseType(type, out type) || !HasComponent(type)) { value = default; return(false); } TComponent result; try { result = TypeConstruction.Construct <TComponent>(type); } catch (Exception e) { Debug.LogError($"Failed to construct type '{type.FullName}'.\n{e.Message}"); value = default; return(false); } for (var i = 0; i < Dependencies.Count; ++i) { var dependency = Dependencies[i]; if (dependency == null || !dependency) { continue; } if (dependency.TryGetComponent(type, out var component)) { CopyComponent(ref result, ref component); } } for (var i = 0; i < Components.Count; ++i) { var component = Components[i]; if (component.GetType() == type) { CopyComponent(ref result, ref component); break; } } value = result; return(true); }
static void ConstructFromSerializedType <TValue>(ref TValue value, Type type, ISerializedTypeProvider provider) { if (type.IsArray) { var count = provider.GetArrayLength(); value = TypeConstruction.ConstructArray <TValue>(type, count); return; } if (null != value && value.GetType() == type) { return; } value = TypeConstruction.Construct <TValue>(type); }
public TestData(params Type[] components) { BuildStep = new TestBuildStep(); BuildPipeline = BuildPipeline.CreateInstance(p => p.BuildSteps.Add(BuildStep)); BuildSettings = BuildSettings.CreateInstance((s) => { s.SetComponent(new PipelineComponent { Pipeline = BuildPipeline }); foreach (var component in components) { s.SetComponent(component, TypeConstruction.Construct <IBuildSettingsComponent>(component)); } }); BuildContext = new BuildContext(BuildPipeline, BuildSettings, null); }
public void SettingAndUnSettingAnExplicitConstructionMethod_ToCreateAnInstance_BehavesProperly() { Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.False); Assert.That(TypeConstruction.CanBeConstructed(typeof(ParameterConstructorType)), Is.False); TypeConstruction.SetExplicitConstructionMethod(ExplicitConstruction); Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.True); Assert.That(TypeConstruction.CanBeConstructed(typeof(ParameterConstructorType)), Is.True); { var instance = TypeConstruction.Construct <ParameterConstructorType>(); Assert.That(instance, Is.Not.Null); Assert.That(instance.Value, Is.EqualTo(10.0f)); } TypeConstruction.UnsetExplicitConstructionMethod(ExplicitConstruction); Assert.That(TypeConstruction.CanBeConstructed <ParameterConstructorType>(), Is.False); Assert.That(TypeConstruction.CanBeConstructed(typeof(ParameterConstructorType)), Is.False); }
/// <summary> /// Get all optional components from <see cref="BuildConfiguration"/>. /// Optional component types not found in <see cref="BuildConfiguration"/> will be set to a new instance of that type. /// </summary> /// <param name="context">The <see cref="BuildContext"/> used by the execution of this <see cref="BuildStep"/>.</param> /// <returns>List of optional components.</returns> public IEnumerable <IBuildComponent> GetOptionalComponents(BuildContext context) { if (OptionalComponents == null) { return(Enumerable.Empty <IBuildComponent>()); } var lookup = new Dictionary <Type, IBuildComponent>(); foreach (var type in OptionalComponents) { if (!context.BuildConfiguration.TryGetComponent(type, out var component)) { component = TypeConstruction.Construct <IBuildComponent>(type); } lookup[type] = component; } return(lookup.Values); }
static bool ShouldStayNull <TContainer, TValue>( Property <TContainer, TValue> property, ref TContainer container, ref TValue value) { if (property.IsReadOnly || !property.HasAttribute <CreateInstanceOnInspectionAttribute>() || property is ICollectionElementProperty) { return(true); } var attribute = property.GetAttribute <CreateInstanceOnInspectionAttribute>(); if (null == attribute.Type) { if (TypeConstruction.CanBeConstructed <TValue>()) { value = TypeConstruction.Construct <TValue>(); property.SetValue(ref container, value); return(false); } Debug.LogWarning(PropertyChecks.GetNotConstructableWarningMessage(typeof(TValue))); } else { var isAssignable = typeof(TValue).IsAssignableFrom(attribute.Type); var isConstructable = TypeUtility.GetAllConstructableTypes(typeof(TValue)) .Contains(attribute.Type); if (isAssignable && isConstructable) { value = TypeConstruction.Construct <TValue>(attribute.Type); property.SetValue(ref container, value); return(false); } Debug.LogWarning(isAssignable ? PropertyChecks.GetNotConstructableWarningMessage(attribute.Type) : PropertyChecks.GetNotAssignableWarningMessage(attribute.Type, typeof(TValue))); } return(true); }
static void ConstructFromDeclaredType <TValue>(ref TValue value, ISerializedTypeProvider provider) { if (typeof(TValue).IsArray) { var count = provider.GetArrayLength(); if (null == value || (value as Array)?.Length != count) { value = TypeConstruction.ConstructArray <TValue>(count); return; } return; } if (null == value) { value = TypeConstruction.Construct <TValue>(); } }