在通过反射实例化时将类型的实例添加到该类型的列表中

本文关键字:类型 添加 列表 实例 实例化 反射 | 更新日期: 2023-09-27 18:32:19

我正在尝试通过使用反射来填充多个类的属性,以将默认值分配给它们的所有属性。

这主要是通过使用 PropertyInfo.Setvalue(instance, value) 来完成的。但是,当该属性具有特定类的列表时,我遇到了问题。直到运行时我才知道该类类型。

要创建该列表并返回到 SetVaule() 设置,我正在执行以下操作:

    private static IEnumerable<object> CreateAListContainingOneObject(Type type)
    {
        var listType = typeof(List<>).MakeGenericType(new Type[] { type });
        var generic = Activator.CreateInstance(listType);
        var dynamicList = generic as dynamic;
         var instance = new MySpecialType();
         var instance2 = Activator.CreateInstance(type);
        var typecheck = instance.GetType() == instance2.GetType();
        dynamicList.Add(instance);
        dynamicList.Add(instance2);
        return dynamicList;
    }

我已经尝试了几个选项,但这里列出的一个特别有趣,因为当运行时类型检查将为真,第一个 Add 将起作用,但第二个将失败,告诉我"最好的重载方法'Add(....)'有一些无效的参数"。

附言。该列表必须是MyType的列表,否则我将无法通过SetVaule()将其值设置为该属性。使用新的对象列表并添加 myType 类型的新实例化对象将不起作用。

编辑:我没有使用泛型方法来调用我可以实例化已知类型的原因是因为我是在从基类继承的一系列类上执行此操作的。它们具有多种属性,我无法知道也不想为每个类及其可能具有的每个属性编写代码。调用源自如下内容:

public static ABaseClass FillObjectWithDefaults(this ABaseClass myObject)
    {
        var properties = myObject.GetType().GetProperties();
        foreach (var p in properties)
        {
             var value = FindValue(p);
             p.SetValue(template, value);
        }
        return template;
    }

在通过反射实例化时将类型的实例添加到该类型的列表中

您可以使用第二种通用方法来帮助您,这样您就不需要弄乱动态和激活。

这只涉及查找帮助程序方法并调用该方法来创建实例并将其添加到列表中。它还为您提供了一般调用它的选项。

private static IEnumerable<object> CreateAListContainingOneObject(Type type)
{
    var del = typeof(Program).GetMethod("CreateAGenericListContainingOneObject",
        BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type);
    return del.Invoke(null, new object[] { }) as IEnumerable<object>;
}
private static List<T> CreateAGenericListContainingOneObject<T>()
    where T : new()
{
    return new List<T> { new T() };
}

示例 DotNetFiddle

Activator.CreateInstance返回类型为 Object 的对象,因此第二个Add不起作用。

您可以投射它:

var instance2 = Activator.CreateInstance(type) as MySpecialType;
var instance2 = (MySpecialType)Activator.CreateInstance(type);

或使用dynamic而不是var

dynamic instance2 = Activator.CreateInstance(type);

就个人而言,我可能会完全更改函数以使用如下所示的泛型类型参数:

private static IEnumerable<object> CreateAListContainingOneObject<T>()
{
    var listType = typeof(List<>).MakeGenericType(typeof(T));
    var generic = Activator.CreateInstance(listType);
    var dynamicList = generic as dynamic;
    var instance = new MySpecialType();
    var instance2 = (T)Activator.CreateInstance(typeof(T));
    var typecheck = instance.GetType() == instance2.GetType();
    dynamicList.Add(instance);
    dynamicList.Add(instance2);
    return dynamicList;
}

并像这样称呼它:

var list = CreateAListContainingOneObject<MySpecialType>();