Пример #1
0
        /// <summary>
        /// Gets all objects of type <typeparamref name="T"/> referenced through passed object <paramref name="o"/>
        /// contained in the lump <paramref name="lumpName"/> stored in this <see cref="BSP"/> class. This is done by
        /// reflecting the <c>Type</c> of <paramref name="o"/> and looping through its public properties to find
        /// a member with an <see cref="IndexAttribute"/> attribute and a member with a <see cref="CountAttribute"/> attribute
        /// both corresponding to <paramref name="lumpName"/>. The index and count are obtained and used to construct
        /// a new <c>List&lt;<typeparamref name="T"/>&gt;</c> object containing the corresponding objects.
        /// </summary>
        /// <typeparam name="T">The type of <c>object</c> stored in the lump <paramref name="lumpName"/>.</typeparam>
        /// <param name="o">The <c>object</c> which contains and index and count corresponding to <paramref name="lumpName"/>.</param>
        /// <param name="lumpName">The name of the property in this <see cref="BSP"/> object to get a <c>List</c> of objects from.</param>
        /// <returns>The <c>List&lt;<typeparamref name="T"/>&gt;</c> of objects in the lump from the index and length specified in <paramref name="o"/>.</returns>
        /// <exception cref="ArgumentException">The <see cref="BSP"/> class contains no property corresponding to <paramref name="lumpName"/>.</exception>
        /// <exception cref="ArgumentException">The <c>object</c> referenced by <paramref name="o"/> is missing one or both members with <c>IndexAttribute</c> or <c>CountAttribute</c> attributes corresponding to <paramref name="lumpName"/>.</exception>
        /// <exception cref="ArgumentNullException">One or both of <paramref name="o"/> or <paramref name="lumpName"/> is null.</exception>
        public List <T> GetReferencedObjects <T>(object o, string lumpName)
        {
            if (o == null)
            {
                throw new ArgumentNullException("Object cannot be null.");
            }
            if (lumpName == null)
            {
                throw new ArgumentNullException("Lump name cannot be null.");
            }
            // First, find the property in this class corresponding to lumpName, and grab its "get" method
            PropertyInfo targetLump = typeof(BSP).GetProperty(lumpName, BindingFlags.Public | BindingFlags.Instance);

            if (targetLump == null)
            {
                throw new ArgumentException("The lump " + lumpName + " does not exist in the BSP class.");
            }

            // Next, find the properties in the passed object corresponding to lumpName, through the Index and Length custom attributes
            Type objectType = o.GetType();

            PropertyInfo[] objectProperties = objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo   indexProperty    = null;
            PropertyInfo   countProperty    = null;

            foreach (PropertyInfo info in objectProperties)
            {
                IndexAttribute indexAttribute = info.GetCustomAttribute <IndexAttribute>();
                if (indexAttribute != null)
                {
                    if (indexAttribute.lumpName == lumpName)
                    {
                        indexProperty = info;
                        if (indexProperty != null && countProperty != null)
                        {
                            break;
                        }
                    }
                }
                CountAttribute lengthAttribute = info.GetCustomAttribute <CountAttribute>();
                if (lengthAttribute != null)
                {
                    if (lengthAttribute.lumpName == lumpName)
                    {
                        countProperty = info;
                        if (indexProperty != null && countProperty != null)
                        {
                            break;
                        }
                    }
                }
            }
            if (indexProperty == null || countProperty == null)
            {
                throw new ArgumentException("An object of type " + objectType.Name + " does not implement both an Index and Count for lump " + lumpName + ".");
            }

            // Get the index and length from the object
            int index = (int)(indexProperty.GetGetMethod().Invoke(o, null));
            int count = (int)(countProperty.GetGetMethod().Invoke(o, null));

            // Get the lump from this class
            List <T> theLump = targetLump.GetGetMethod().Invoke(this, null) as List <T>;

            return(theLump.GetRange(index, count));
        }
Пример #2
0
        /// <summary>
        /// Gets all objects of type <typeparamref name="T"/> referenced through passed object <paramref name="o"/>
        /// contained in the lump <paramref name="lumpName"/> stored in this <see cref="BSP"/> class. This is done by
        /// reflecting the <c>Type</c> of <paramref name="o"/> and looping through its public properties to find
        /// a member with an <see cref="IndexAttribute"/> attribute and a member with a <see cref="CountAttribute"/> attribute
        /// both corresponding to <paramref name="lumpName"/>. The index and count are obtained and used to construct
        /// a new <c>List&lt;<typeparamref name="T"/>&gt;</c> object containing the corresponding objects.
        /// </summary>
        /// <typeparam name="T">The type of <c>object</c> stored in the lump <paramref name="lumpName"/>.</typeparam>
        /// <param name="o">The <c>object</c> which contains and index and count corresponding to <paramref name="lumpName"/>.</param>
        /// <param name="lumpName">The name of the property in this <see cref="BSP"/> object to get a <c>List</c> of objects from.</param>
        /// <returns>The <c>List&lt;<typeparamref name="T"/>&gt;</c> of objects in the lump from the index and length specified in <paramref name="o"/>.</returns>
        /// <exception cref="ArgumentException">The <see cref="BSP"/> class contains no property corresponding to <paramref name="lumpName"/>.</exception>
        /// <exception cref="ArgumentException">The <c>object</c> referenced by <paramref name="o"/> is missing one or both members with <c>IndexAttribute</c> or <c>CountAttribute</c> attributes corresponding to <paramref name="lumpName"/>.</exception>
        /// <exception cref="ArgumentNullException">One or both of <paramref name="o"/> or <paramref name="lumpName"/> is null.</exception>
        public List <T> GetReferencedObjects <T>(object o, string lumpName)
        {
            if (o == null)
            {
                throw new ArgumentNullException("Object cannot be null.");
            }
            if (lumpName == null)
            {
                throw new ArgumentNullException("Lump name cannot be null.");
            }
            // First, find the property in this class corresponding to lumpName, and grab its "get" method
            PropertyInfo targetLump = typeof(BSP).GetProperty(lumpName, BindingFlags.Public | BindingFlags.Instance);

            if (targetLump == null)
            {
                throw new ArgumentException("The lump " + lumpName + " does not exist in the BSP class.");
            }

            // Next, find the properties in the passed object corresponding to lumpName, through the Index and Length custom attributes
            Type objectType = o.GetType();

            PropertyInfo[] objectProperties = objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo   indexProperty    = null;
            PropertyInfo   countProperty    = null;

            foreach (PropertyInfo info in objectProperties)
            {
                IndexAttribute indexAttribute = info.GetCustomAttribute <IndexAttribute>();
                if (indexAttribute != null)
                {
                    if (indexAttribute.lumpName == lumpName)
                    {
                        indexProperty = info;
                        if (indexProperty != null && countProperty != null)
                        {
                            break;
                        }
                    }
                }
                CountAttribute lengthAttribute = info.GetCustomAttribute <CountAttribute>();
                if (lengthAttribute != null)
                {
                    if (lengthAttribute.lumpName == lumpName)
                    {
                        countProperty = info;
                        if (indexProperty != null && countProperty != null)
                        {
                            break;
                        }
                    }
                }
            }
            if (indexProperty == null || countProperty == null)
            {
                throw new ArgumentException("An object of type " + objectType.Name + " does not implement both an Index and Count for lump " + lumpName + ".");
            }

            // Get the index and length from the object
            int index = (int)(indexProperty.GetGetMethod().Invoke(o, null));
            int count = (int)(countProperty.GetGetMethod().Invoke(o, null));

            // Get the lump from this class
            IList <T> theLump = targetLump.GetGetMethod().Invoke(this, null) as IList <T>;

            // Copy items from the lump into a return list.
            // IList<T> lacks AddRange and this is faster and creates less garbage than any Linq trickery I could come up with.
            // Passing references to IList<T> out of this method just eats obscene amounts of memory until the system runs out.
            List <T> ret = new List <T>(count);

            for (int i = 0; i < count; ++i)
            {
                ret.Add(theLump[index + i]);
            }
            return(ret);
        }