using System; using System.Reflection; using UnityEditor.Build.Pipeline.Interfaces; namespace UnityEditor.Build.Pipeline.Injector { /// /// Use to pass around information between build tasks. /// [AttributeUsage(AttributeTargets.Field)] public class InjectContextAttribute : Attribute { //public string Identifier { get; set; } /// /// Stores the how the attribute is used among build tasks. /// public ContextUsage Usage { get; set; } /// /// Stores whether using the context attribute is optional. /// public bool Optional { get; set; } /// /// Creates a new context attribute that stores information that can be passed between build tasks. /// /// The usage behavior for the attribute. By default it is set to . /// Set to true if using the attribute is optional. Set to false otherwise. public InjectContextAttribute(ContextUsage usage = ContextUsage.InOut, bool optional = false) { this.Usage = usage; Optional = optional; } } /// /// Options for how the attribute is used among build tasks. It can be either injected to and or extracted from a build task. /// public enum ContextUsage { /// /// Use to indicate that the attribute can be injected to and extracted from a build task. /// InOut, /// /// Use to indicate that the attribute can only be injected to a build task. /// In, /// /// Use to indicate that the attribute can only be extracted from a build task. /// Out } class ContextInjector { public static void Inject(IBuildContext context, object obj) { FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { object[] attrs = field.GetCustomAttributes(typeof(InjectContextAttribute), true); if (attrs.Length == 0) continue; InjectContextAttribute attr = attrs[0] as InjectContextAttribute; if (attr == null || attr.Usage == ContextUsage.Out) continue; object injectionObject; if (field.FieldType == typeof(IBuildContext)) injectionObject = context; else if (!attr.Optional) injectionObject = context.GetContextObject(field.FieldType); else { IContextObject contextObject; context.TryGetContextObject(field.FieldType, out contextObject); injectionObject = contextObject; } field.SetValue(obj, injectionObject); } } public static void Extract(IBuildContext context, object obj) { FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { object[] attrs = field.GetCustomAttributes(typeof(InjectContextAttribute), true); if (attrs.Length == 0) continue; InjectContextAttribute attr = attrs[0] as InjectContextAttribute; if (attr == null || attr.Usage == ContextUsage.In) continue; if (field.FieldType == typeof(IBuildContext)) throw new InvalidOperationException("IBuildContext can only be used with the ContextUsage.In option."); IContextObject contextObject = field.GetValue(obj) as IContextObject; if (!attr.Optional) context.SetContextObject(field.FieldType, contextObject); else if (contextObject != null) context.SetContextObject(field.FieldType, contextObject); } } } }