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

时间:2014-11-28 15:44:15

标签: c# generics reflection

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

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

要创建该列表并返回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;
    }

我已经尝试了几个选项,但是这里列出的选项特别有趣,因为在运行时,typecheck将为true,第一个Add将起作用,但第二个将失败,告诉我“最好的重载方法”Add(。 ......)'有一些无效的论点“。

PS。该列表必须是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;
    }

2 个答案:

答案 0 :(得分:1)

您可以使用第二种通用​​方法来帮助您,因此您不需要动摇动态和激活。

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

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() };
}

Example DotNetFiddle

答案 1 :(得分:0)

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>();