Skip to content

Cloning of subtypes on non-abstract type #43

Description

@MizardX

When using the source generator, [FastClonerClonable] only registers the root type unless the class is abstract. If you also add the attribute to subtypes, they get their own clone methods, but no type dispatcher. [FastClonerInclude] is ignored, since the type is neither abstract nor generic.

In this code example, only the last abstract case works. I want to be able to clone the subtype when the variable is of the base type somehow. Neither using [FastClonerInclude] nor adding [FastClonerClonable] to subtypes generates the dispatch code like for abstract types.

Code examples
  • Include + direct class: The source generator does not know of the subtype at all, so it clones it into the base type.
  • Include + base class: Same
  • Subtype clonable + direct class: The source generator use the subtype implementation
  • Subtype clonable + base class: Since the generic parameter is the base type, it clones it as the base type again.
  • Abstract base type + base class: This works as expected, but requires the base type to be abstract.
#:package FastCloner.SourceGenerator@*
#:property PublishAot=false
// ^--for JsonSerializer reflection

using FastCloner.SourceGenerator.Shared;
using System.Text.Json;

var x11 = new Sub1 { X = 1, Y = 1 };
var y11 = x11.FastDeepClone();

Console.WriteLine($"Include + direct class: {y11?.GetType().Name} {JsonSerializer.Serialize(y11)}");

Base1 x12 = new Sub1 { X = 1, Y = 12 };
var y12 = x12.FastDeepClone();

Console.WriteLine($"Include + base class: {y12?.GetType().Name} {JsonSerializer.Serialize(y12)}");

var x21 = new Sub2 { X = 1, Y = 2 };
var y21 = x21.FastDeepClone();

Console.WriteLine($"Subtype clonable + direct class: {y21?.GetType().Name} {JsonSerializer.Serialize(y21)}");

Base2 x22 = new Sub2 { X = 1, Y = 2 };
var y22 = x22.FastDeepClone();

Console.WriteLine($"Subtype clonable + base class: {y22?.GetType().Name} {JsonSerializer.Serialize(y22)}");

Base3 x3 = new Sub3 { X = 1, Y = 2 };
var y3 = x3.FastDeepClone();

Console.WriteLine($"Abstract base type + base class: {y3?.GetType().Name} {JsonSerializer.Serialize(y3)}");

[FastClonerClonable]
[FastClonerInclude(typeof(Sub1))]
public class Base1
{
    public int X { get; set; }
}

public class Sub1 : Base1
{
    public int Y { get; set; }
}

[FastClonerClonable]
public class Base2
{
    public int X { get; set; }
}

[FastClonerClonable]
public class Sub2 : Base2
{
    public int Y { get; set; }
}

[FastClonerClonable]
public abstract class Base3 {
    public int X { get; set; }
}

public class Sub3 : Base3
{
    public int Y { get; set; }
}

Output:

Include + direct class: Base1 {"X":1}
Include + base class: Base1 {"X":1}
Subtype clonable + direct class: Sub2 {"Y":2,"X":1}
Subtype clonable + base class: Base2 {"X":1}
Abstract base type + base class: Sub3 {"X":1}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions