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}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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