Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] how to have a abstract class/interface as a property/field without knowing the type before #20

Closed
TMaddox opened this issue Sep 2, 2019 · 7 comments
Assignees
Labels
question Further information is requested

Comments

@TMaddox
Copy link

TMaddox commented Sep 2, 2019

I know this is possible #11, but have you got any any idea on how I could use this if I do not know the type?

public class Tree
{
        public Fruit { get; set; }
        ...
}

public abstract class Fruit { ... }

public class Apple : Fruit { ... }
public class Orange : Fruit { ... }
@mcatanzariti mcatanzariti self-assigned this Sep 2, 2019
@mcatanzariti mcatanzariti added the question Further information is requested label Sep 2, 2019
@mcatanzariti
Copy link
Member

The implementation of polymorphism in Dahomey.Cbor is based on a special field in which a special value is associated with an inherited class. The special field/value is called discriminator.

By default the discriminator field is named "_t" and the discriminator values are configured

  1. Either by using the attribute CborDiscriminatorAttribute:
[CborDiscriminator("Apple")]
public class Apple : Fruit { ... }

[CborDiscriminator("Orange")]
public class Orange : Fruit { ... }

Moreover , in this option, you need to register the assembly to allow the framework to discover the classed flagged by the CborDiscriminatorAttribute:

CborOptions.Default.Registry.DefaultDiscriminatorConvention.RegisterAssembly(typeof(Fruit ).Assembly);
  1. Or by API:
options.Registry.ObjectMappingRegistry.Register<Apple>(om => om.AutoMap().SetDiscriminator("Apple");
options.Registry.ObjectMappingRegistry.Register<Orange>(om => om.AutoMap().SetDiscriminator("Orange");

@TMaddox
Copy link
Author

TMaddox commented Sep 2, 2019

I tried both examples and I also added the [CborDiscriminator("Name")] attribute on all classes implementing the Fruit class, but it still throws:
CborException: A CreatorMapping should be defined for interfaces or abstract classes

@mcatanzariti I am mentioning you by name because I do not have the permission to reopen this issue, but I feel like I should ask here.

@mcatanzariti
Copy link
Member

mcatanzariti commented Sep 2, 2019

Did you try with the last official version?
The 2 examples I gave you are integrated in the automated tests and they don't fail

@TMaddox
Copy link
Author

TMaddox commented Sep 2, 2019

yes with 1.3.2, I have broken it down to tree classes while testing and found out the following:

    public class Tree
    {
        [CborProperty("age")]
        public readonly int _age;
        
        [CborProperty("fruit")]
        public Fruit _fruit;

        [CborConstructor]
        public Tree(int age, Fruit fruit)
        {
            _age = age;
            _fruit = fruit;
        }
    }

    public abstract class Fruit
    {
        public string id2 = "myid"; // if I remove this it won't throw
    }

    [CborDiscriminator("Apple")]
    public class Apple : Fruit
    {
        [CborProperty("type")]
        public const string type = "I am an apple";
    }

    [CborDiscriminator("Orange")]
    public class Orange : Fruit
    {
        [CborProperty("type")]
        public const string type = "I am an orange";
    }

@TMaddox
Copy link
Author

TMaddox commented Sep 2, 2019

further, serializing the above example will output {"age": 10, "fruit": {}, "id": "123"}, with fruit being empty, I have tried it with const fields and normal ones in combination with a constructor.

@mcatanzariti
Copy link
Member

Reproduced

@mcatanzariti mcatanzariti reopened this Sep 2, 2019
@mcatanzariti
Copy link
Member

fix in 1.4.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants