-
-
Notifications
You must be signed in to change notification settings - Fork 55
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
Option for avoiding mapping on the Parent #26
Comments
Hi, I agree that it might be better to do the mapping on the child instead of the parent. In branch feature/base-without-useless-property I have support for the case you're exposing (having no possibility to add attributes on the parent) JsonConvert.DefaultSettings = () => new JsonSerializerSettings();
var settings = JsonConvert.DefaultSettings();
settings.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(IAnimal), "Breed")
.RegisterSubtype(typeof(Dog), "Dog")
.RegisterSubtype(typeof(Cat), "Cat")
.Build());
IAnimal animal = new Dog();
var json = JsonConvert.SerializeObject(animal, settings);
JsonConvert.DeserializeObject<IExpression2>(json, settings); But it have situations where I did not managed yet to fix some edge cases, so it's not released yet. |
If [JsonConverter(typeof(JsonSubtypes), "Breed")]
public interface IAnimal
{
string Breed {get;set;}
} The concrete type whitout attributes: public class Dog : IAnimal
{
public string Breed {get;set;} = "Dog";
public bool HasChip {get;set;}
}
public class Cat : IAnimal
{
public string Breed {get;set;} = "Cat";
public bool HasClaws {get;set;}
} // the mapping setup
TypeDescriptor.AddAttributes(typeof(IAnimal),
new JsonSubtypes.KnownSubTypeAttribute(typeof(Cat), "cat"),
new JsonSubtypes.KnownSubTypeAttribute(typeof(Dog), "dog"));
var json = "{\"catLives\":6,\"@type\":\"cat\",\"age\":11}";
var result = JsonConvert.DeserializeObject<Animal>(json);
Assert.AreEqual(typeof(Cat), result.GetType());
Assert.AreEqual(11, result.Age);
Assert.AreEqual(6, (result as Cat)?.Lives); But |
They both are great ideas. How close is the 1st option? If is good enough to test for the standard use cases (maybe just part it as experimental and release it?) |
The 1st option is now released in v1.3.0 with #28 |
I think I found an issue with #28 - if the interface and the concrete class is in different assemblies there is an issue in creating the concrete instance. I think the issue is when the interface and class are in different name space. It looks like their is an assumption in the code that the namespace for the interface is used to build the namespace for the class. |
@ravensorb I tried to reproduce the issue you described but did not managed (see: https://github.com/manuc66/JsonSubTypes/tree/bugfix/try-to-reproduce-bug). Can you provide some sample code and open an new issue with it? Thanks |
So I tracked it down -- it looks like the code assumes that everything is in a single assembly (interface and classes). For my scenario I have the interface in one assembly and the concrete classes spread out over several other assemblies. To repro create 3 assemblies
This will show the issue. Now the hard part is, I am not sure what the solution might be as you are supporting a lot of the legacy frameworks via PCL (I think) and up until the latest version AppDomain is not usable which makes getting a list of all loaded assemblies a bit tricky from what I can remember. |
When dynamic registration is used (which has been introduced with #28) the sub type should be is taken from the registration and not from the parent type assembly. With #28 the method GetSubTypeMapping is overrided and then should provides some values so it did not fall in the GetTypeByName (which build the subtype from the assemble of the parent, but not in this case). |
issue with that is, it assumes that everything is loaded immediately and that is not always the case when you have things handled via DI |
Love your implementation. I was curious any thoughts to adding support for doing the mapping on the child instance instead of the parent? This would provide better support for a more flexible IoC pattern -
Example: The interface is defined in one assembly by a framework author
and then the concrete implementation would be in another file (or assembly)
this could be implemented using the DependencyInjection or by using Reflection for all known types loaded (supporting the DI pattern would be more ideal I think)
Thoughts?
The text was updated successfully, but these errors were encountered: