无法将子类对象放入列表中

本文关键字:列表 对象 子类 | 更新日期: 2023-09-27 18:18:43

您能帮我编写一个创建对象列表的方法吗?

  1. 我有一个类有3个子类。
  2. 我创建了一个方法,将所有子类放入列表中。
  3. 现在我在创建包含对象的列表时遇到了问题-从步骤2中每个子类一个。
  4. 请注意,列表应该有父类的类类型,因为它会多态引用子类的对象。

澄清:我想要一个类似于

的列表
List<Class01> list = new List<Class01>();
list.Add(new SubClass0101());
list.Add(new SubClass0102());
list.Add(new SubClass0103());

,但它必须自动增长,如果子类的数量增加

问题:我需要帮助 private static IEnumerable<Type> PopulateListWithObjects<TClass>()

请参阅下面的代码以获取更多详细信息。

using System;
using System.Collections.Generic;
using System.Linq;
namespace PutObjectsInList
{
    class Program
    {
        static void Main(string[] args)
        {
            // Puts all subclasses of Class01 into the list
            var listOfSubClasses = SubClasses<Class01>();
            // Verifies that listOfSubClasses is populated with the subclasses names
            foreach (var listOfSubClass in listOfSubClasses) {Console.WriteLine(listOfSubClass);}
            var listWithObjects = PopulateListWithObjects<Class01>();
        }
        //
        private static IEnumerable<TClass> PopulateListWithObjects<TClass>()
        {
            var listWithObjects = new List<TClass>();
            // Need help with the procedure which would populate list with the
            // objects of the subclasses of the parent Class01
            return listWithObjects;
        }
        // Enumerates all subclasses for the specified class
        private static IEnumerable<Type> SubClasses<TClass>()
        {
            var subclasses =
                (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                 from type in assembly.GetTypes()
                 where type.IsSubclassOf(typeof(TClass))
                 select type).ToList();
            return subclasses;
        }
    }
    public class Class01 {}
    public class SubClass0101 : Class01 {}
    public class SubClass0102 : Class01 {}
    public class SubClass0103 : Class01 {}
}

无法将子类对象放入列表中

如果你想达到预期的结果,你的private static IEnumerable<Type> PopulateListWithObjects<TClass>应该有IEnumerable<TClass>的返回类型。

因为Type表示的不是某种类型的对象,而是它们的类型元数据标识符System.Type

对于实例的创建(实例化),您可以使用Activator.CreateInstance()方法。

最后看起来像:

    private static IEnumerable<TClass> PopulateListWithObjects<TClass>()
    {
        return ReflectorHelper.GetAndActivateAllAssignableTo<TClass>();
    }

GetAndActivateAllAssignableTo定义为:

 public static class ReflectorHelper
{
    /// <summary>
    /// Fetches and prepares for initialization without any constructor parameters all types in the current application domain which are assignable to T.
    /// </summary>
    /// <typeparam name="T">The type to which all desired types should be assignable to.</typeparam>
    /// <returns>IEnumerable of initialized objects.</returns>
    public static IEnumerable<T> GetAndActivateAllAssignableTo<T>()
    {
        return GetAndActivateAllAssignableTo<T>(null);
    }
    /// <summary>
    /// Fetches and prepares for initialization with a given constructor parameters all types in the current application domain which are assignable to T.
    /// </summary>
    /// <typeparam name="T">The type to which all desired types should be assignable to.</typeparam>
    /// <param name="consParams">The constructore parametes array - could be null</param>
    /// <returns>IEnumerable of initialized objects.</returns>
    public static IEnumerable<T> GetAndActivateAllAssignableTo<T>(object[] consParams)
    {
        //Deal with null reference for better code consistency
        if (consParams == null)
            consParams = new object[0];
        return from type in AppDomain.CurrentDomain.GetAllAssignableTo<T>()
               where type.IsInstantiable()
               select (T)Activator.CreateInstance(type, consParams);
    }
    /// <summary>
    /// Gets the flag which shows whether an object of a given type could be possibly(not guaranteed) instantiated.
    /// </summary>
    /// <param name="type">The type to check.</param>
    /// <returns>The flag which shows whether an object of a given type could be possibly(not guaranteed) instantiated.</returns>
    public static Boolean IsInstantiable(this Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type", "The type is null");
        if (type.IsAbstract)
            return false;
        if (type.IsGenericTypeDefinition)
            return false;
        if (type.IsInterface)
            return false;
        return true;
    }
    /// <summary>
    /// Gets all types which are assignable to T type variables.
    /// </summary>
    /// <typeparam name="T">The type to which desired types should be assignable.</typeparam>
    /// <param name="appDomain">The app domain which assemblies should be checked</param>
    /// <returns>The IEnumerable of all types which are assignable to T type variables.</returns>
    public static IEnumerable<Type> GetAllAssignableTo<T>(this AppDomain appDomain)
    {
        if (appDomain == null)
            throw new ArgumentNullException("appDomain", "The app domain is null");
        return GetAllAssignableTo(appDomain, typeof(T));
    }

    /// <summary>
    /// Gets all types which are assignable to T type variables.
    /// </summary>
    /// <param name="appDomain">The app domain which assemblies should be checked</param>
    /// <param name="assignToType">The type to which desired types should be assignable.</param>
    /// <returns>The IEnumerable of all types which are assignable to T type variables.</returns>
    public static IEnumerable<Type> GetAllAssignableTo(this AppDomain appDomain, Type assignToType)
    {
        if (appDomain == null)
            throw new ArgumentNullException("appDomain", "The app domain is null");
        if (assignToType == null)
            throw new ArgumentNullException("assignToType", "The type to check is null");
        return from asm in appDomain.GetAssemblies()
               from type in asm.GetExportedTypes()
               where assignToType.IsAssignableFrom(type)
               select type;
    }
}
编辑:

@Tracey23是的,它不完全是你想要的。它实例化了所有可赋值给TClass的类(!!在这段代码中,TClass甚至可以是一个接口!!),任何TClass当然都可以赋值给TClass

对于这个解决方案,您可以使您的基类abstract,因为除了作为组件的基类之外,您可以将其用于任何其他功能,或者将GetAllAssignableTo更改为在条件下使用(!assignToType.Equals(type)):

    public static IEnumerable<Type> GetAllAssignableTo(this AppDomain appDomain, Type assignToType)
    {
        if (appDomain == null)
            throw new ArgumentNullException("appDomain", "The app domain is null");
        if (assignToType == null)
            throw new ArgumentNullException("assignToType", "The type to check is null");
        return from asm in appDomain.GetAssemblies()
               from type in asm.GetExportedTypes()
               where assignToType.IsAssignableFrom(type) && (!assignToType.Equals(type)) // !!!!!!
               select type;
    }

但是它会改变语义,所以您可能想要重命名这些方法,以反映它们将不再在结果中包含Base类型

从固定返回类型开始。

SubClasses<TClass>()返回IEnumerable<Type>,因为它返回一个类型对象序列。PopulateListWithObjects<TClass>()将返回一个包含给定类型实例的列表,所以List<>的类型参数应该是最派生的基类——我想这将是TClass。换句话说,我认为你的意思是

private static IEnumerable<TClass> PopulateListWithObjects<TClass>()
{
    var listWithObjects = new List<TClass>();
    // todo: add objects here
    return listWithObjects; 
}

现在,您将如何实际创建实例并将其放入列表是另一个问题,您还没有给出足够的信息来回答这个问题。