c# - 根据具有属性的属性复制派生类的实例

标签 c# inheritance reflection attributes

假设我有一个抽象基类,我想要一个 CreateCopy 方法:

public abstract class BaseClass
{
    ///base stuff

    public BaseClass CreateCopy() //or public object, if necessary   
    {
        //?????
    }
}

假设所有派生类都有一个无参数的构造函数和属性字段(可以)标记有某种属性:

public class DerivedClass : BaseClass
{
    [CopiableProperty]
    public string Property1 {get; private set;}

    [CopiableProperty]
    public int Property2 {get; private set;}

    //no need to copy
    public int Property3 {get; private set;}

    //parameterless constructor
    public DerivedClass() { }
}

是否可以使用此结构编写 CreateCopy() 的主体,以便我可以使用正确的 CopiableProperty 字段创建派生对象的新实例?


自然地,我可以制作一个public abstract BaseClass CreateCopy() 并强制每个派生类维护自己的副本,但是由于派生类的大小和数量,这会带来太多额外的努力。

最佳答案

一个相当简单的方法可能是使用泛型和反射:

public abstract class BaseClass
{
    // restrict to children of BaseClass
    public T CreateCopy<T>() where T: BaseClass, new()
    {
        var copy = new T();

        // get properties that you actually care about
        var properties = typeof(T).GetProperties()
            .Where(x => x.GetCustomAttribute<CopiablePropertyAttribute>() != null);

        foreach (var property in properties)
        {
            // set the value to the copy from the instance that called this method
            property.SetValue(copy, property.GetValue(this));
        }

        return copy;
    }
}

public class DerivedClass : BaseClass
{
    [CopiableProperty]
    public string Property1 { get; set; }

    [CopiableProperty]
    public int Property2 { get; set; }

    public int Property3 { get; set; }

    public override string ToString()
    {
        return $"{Property1} - {Property2} - {Property3}";
    }
}

static void Main(string[] args)
{
    var original = new DerivedClass
    {
        Property1 = "Hello",
        Property2 = 123,
        Property3 = 500
    };

    var copy = original.CreateCopy<DerivedClass>();

    Console.WriteLine(original);
    Console.WriteLine(copy);

    Console.ReadLine();
}

这将打印:

Hello - 123 - 500
Hello - 123 - 0

另一种方法是利用序列化库,如果你不介意依赖的话:

public abstract class BaseClass
{
    public BaseClass CreateCopy()
    {
        string serialized = JsonConvert.SerializeObject(this);

        var actualType = GetType();

        return JsonConvert.DeserializeObject(serialized, actualType) as BaseClass;
    }
}

public class DerivedClass : BaseClass
{
    public string Property1 { get; set; }

    public int Property2 { get; set; }

    [JsonIgnore]
    public int Property3 { get; set; }

    //parameterless constructor
    public DerivedClass() { }

    public override string ToString()
    {
        return $"{Property1} - {Property2} - {Property3}";
    }
}

关于c# - 根据具有属性的属性复制派生类的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51402258/

相关文章:

c# - 模拟具有两个参数的方法时出错

java - java中的新关键字

java - 使用构建器模式扩展类

java - 使用反射访问DialogFragment中的一些字段

c# - 设备 Wavecom 调制解调器不支持 SmsSubmitPdu GSMComm 命令

c# - Math.Pow 取整数值

c# - 使用 C# winform 的 zeromq pub/sub 示例

c++ - 通过 "a pointer of the base class"访问未在基类中声明的子类的方法或属性(动态)

c# - 查找在控件中具有属性的属性

c# - 表达式树使用类的属性值创建字典