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}
When using the source generator,
[FastClonerClonable]only registers the root type unless the class isabstract. 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
Output: