コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
 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>());
 }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
 /// <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);
 }
コード例 #8
0
        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));
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        /// <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));
        }
コード例 #11
0
        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)));
        }
コード例 #12
0
        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));
        }
コード例 #13
0
        /// <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);
        }
コード例 #14
0
        /// <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);
        }
コード例 #15
0
 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);
 }
コード例 #16
0
        /// <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);
        }
コード例 #17
0
        /// <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);
        }
コード例 #18
0
        /// <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);
        }
コード例 #19
0
        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);
        }
コード例 #20
0
        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));
        }
コード例 #21
0
        /// <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));
        }
コード例 #22
0
        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));
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        /// <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);
        }
コード例 #25
0
        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);
        }
コード例 #26
0
 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);
 }
コード例 #27
0
        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);
        }
コード例 #28
0
        /// <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);
        }
コード例 #29
0
        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);
        }
コード例 #30
0
        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>();
            }
        }