C#反射列表:对象与目标类型不匹配

3

尝试使用反射将一个类对象添加到列表中,但是当用我的类对象作为参数调用Add方法时,我得到了“对象不符合目标类型”的错误。

以下是相关的代码片段(您可以暂时假设classString = “Processor”):

PC fetched = new PC();

// Get the appropriate computer field to write to
FieldInfo field = fetched.GetType().GetField(classString);

// Prepare a container by making a new instance of the reffered class
// "CoreView" is the namespace of the program.
object classContainer = Activator.CreateInstance(Type.GetType("CoreView." + classString));

/*
    classContainer population code
*/

// This is where I get the error. I know that classContainer is definitely
// the correct type for the list it's being added to at this point.
field.FieldType.GetMethod("Add").Invoke(fetched, new[] {classContainer});

那么上述代码正在向以下类添加 classContainers:

public class PC
{
    public List<Processor> Processor = new List<Processor>();
    public List<Motherboard> Motherboard = new List<Motherboard>();
    // Etc...
}
2个回答

5
您正在尝试在PC上调用List.Add(Processor) - 您需要在字段的值上调用它:
field.FieldType.GetMethod("Add").Invoke(field.GetValue(fetched),
                                        new[] {classContainer});

然而,我个人建议你不要使用这样的公共字段。 考虑改用属性。


成功了!真是太神奇了,每次我公开一个字段时,总会有人抱怨=P。别担心,等我接近程序发布的时候,它们就会变成属性。虽然我还不完全理解为什么它们应该是属性。 - Chris Watts
1
@CJxD:请访问http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx了解更多信息。您甚至可能不想直接公开它们作为列表-您可能只想公开某些操作,例如“AddProcessor”、“AddMotherboard”等。这取决于您希望实现的封装级别。 - Jon Skeet
获取一个代码分析工具并用它来分析你的代码。它会痛苦地嚎叫。如果存在与类型名称相同的成员,不使用属性,暴露具体类型等等问题,这种捷径并没有为你带来任何好处。 public List <Processor> Processors {get; set;}(更好的是 private set),几乎不算什么巨大的不可忍受的负担。 - Tony Hopkinson

0

这个方法将会向所有列表中添加新的项目//只需要使用Add而不是Insert

        IList list = (IList)value;// this what you need to do convert ur parameter value to ilist

        if (value == null)
        {
            return;//or throw an excpetion
        }

        Type magicType = value.GetType().GetGenericArguments()[0];//Get class type of list
        ConstructorInfo magicConstructor = magicType.GetConstructor(Type.EmptyTypes);//Get constructor reference

        if (magicConstructor == null)
        {
            throw new InvalidOperationException(string.Format("Object {0} does not have a default constructor defined", magicType.Name.ToString()));
        }

        object magicClassObject = magicConstructor.Invoke(new object[] { });//Create new instance
        if (magicClassObject == null)
        {
            throw new ArgumentNullException(string.Format("Class {0} cannot be null.", magicType.Name.ToString()));
        }
        list.Insert(0, magicClassObject);
        list.Add(magicClassObject);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接