在C#中将Parent对象强制转换为Child对象

本文关键字:对象 转换 Child 中将 Parent | 更新日期: 2023-09-27 18:29:10

Hi我想在C#中将Parent对象强制转换为Child对象

public class Parent
{
    public string FirstName {get; set;}
    public string LastName {get; set;}
    public string City {get; set;}
}
public class Child : Parent
{
    public string PhoneNumber {get; set;}
    public string MobileNumber {get; set;}
}

现在的场景是一个父对象列表,我想生成子对象列表,这样我就可以获得扩展信息

List<Parent> lstParent;
List<Child> lstChild = new List<Child>();
foreach(var obj in lstParent)
{
    lstChild.add((Child)obj);
}

由于子类继承了父类,所以子类已经有了父类成员,我只想自动填充它们,这样我就可以填充子类的数据成员

在C#中将Parent对象强制转换为Child对象

我这样做(这只是一个例子):

using System.Reflection;
public class DefaultObject
{
    ...
}
public class ExtendedObject : DefaultObject
{
    ....
    public DefaultObject Parent { get; set; }
    public ExtendedObject() {}
    public ExtendedObject(DefaultObject parent)
    {
        Parent = parent;
        foreach (PropertyInfo prop in parent.GetType().GetProperties())
            GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(parent, null), null);
    }
}

使用:

DefaultObject default = new DefaultObject { /* propery initialization */ };
ExtendedObject extended = new ExtendedObject(default); // now all properties of extended are initialized by values of default properties.
MessageBox.Show(extended.Parent.ToString()); // now you can get reference to parent object

如果我正确理解您的"我只想自动填充它们"注释,那么您需要创建一个新的Child对象,该对象使用Parent的值填充,并使用新属性的默认值。最好的方法是创建一个复制值的构造函数:

public class Parent
{
   public string FirstName {get; set;}
    public string LastName {get; set;}
    public string City {get; set;}
}
public class Child : Parent
{
    public string PhoneNumber {get; set;}
    public string MobileNumber {get; set;}
    public Child (Parent parentToCopy)
    {
        this.FirstName = parentToCopy.FirstName;
        this.LastName = parentToCopy.LastName;
        this.City = parentToCopy.City;
        this.PhoneNumber = string.Empty; // Or any other default.
        this.MobileNumber = string.Empty;
    } 
}

现在,您可以使用LINQ,就像上面的答案一样,从每个Parent创建一个Child:

List<Child> lstChild = lstParent.Select(parent => new Child(parent)).ToList();

请注意,这与@daryal的答案非常相似,但将父到子复制逻辑封装在构造函数内部,而不是在new Child()调用外部。

这是我在解决方案中提出的。

    public static void ShallowConvert<T, U>(this T parent, U child)
    {
        foreach (PropertyInfo property in parent.GetType().GetProperties())
        {
            if (property.CanWrite)
            {
                property.SetValue(child, property.GetValue(parent, null), null);
            }
        }
    }

我喜欢这样:

class Parent
{
  ...
}
class Child :Parent
{
  ...
  public Child(Parent p)
  {
            foreach (FieldInfo prop in  p.GetType().GetFields())
                GetType().GetField(prop.Name).SetValue(this, prop.GetValue( p));
            foreach (PropertyInfo prop in  p.GetType().GetProperties())
                GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue( p, null), null);
  }
}
var lstChild = lstParent.Cast<Child>().ToList();

var lstChild = lstParent.ConvertAll(x=>(Child)x);

然而,这两者都假定Parent列表实际上包含Child实例。不能更改对象的实际类型。

您也可以使用反射,但这对您的情况更简单。

foreach(var obj in lstParent)
{
    Child child = new Child(){ FirstName = obj.FirstName, LastName=obj.LastName, City = obj.City};
    child.MobileNumber = "some mobile number";
    child.PhoneNumber = "some phone number";
    lstChild.Add((Child)obj);
}

实现此解决方案的另一种方法是让Parent控制复制逻辑,Child将复制源传递给base构造函数。

例如,在Avner的解决方案上迭代

public class Parent
{
    public string FirstName {get; set;}
    public string LastName {get; set;}
    public string City {get; set;}
    public Parent()
    {
    }
    public Parent(Parent copyFrom)
    {
        this.FirstName = copyFrom.FirstName;
        this.LastName = copyFrom.LastName;
        this.City = copyFrom.City;
    }
}
public class Child : Parent
{
    public string PhoneNumber {get; set;}
    public string MobileNumber {get; set;}
    public Child (Parent parentToCopy) : base(parentToCopy)
    {
    } 
}