你能帮我编写一个创建对象列表的方法吗?
澄清: 我想有一个类似于
的列表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 {}
}
答案 0 :(得分:1)
如果您想获得所需的结果,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
,因为您怀疑是否将其用于组件的基类以外的任何其他容量或更改{{1}在条件中使用GetAllAssignableTo
:
(!assignToType.Equals(type))
但它会改变语义,因此您可能希望重命名此方法以反映它们将不再包含结果中的Base类型。
答案 1 :(得分:0)
首先修复返回类型。
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;
}
现在你要如何实际创建列入列表的实例是另一个问题,而你还没有提供足够的信息来回答它。