Deserialize Object Hierarchy in YAMLDotNet - yamldotnet

I am using YamlDotNet and it works pretty well. I have a quick question about serializing object trees though. For example, I have
class A {
[YamlMember(Alias = "p1")]
public string P1 { get; set; }
}
Then I want to inherit from A like so:
class B : A {
[YamlMember(Alias = "p2")]
public string P2 { get; set; }
}
Finally, I created a document object like this:
class D {
[YamlMember(Alias = "a")]
public A InputA { get; set; }
[YamlMember(Alias = "b")]
public B InputB { get; set; }
}
I deserialized the following Yaml:
a:
p1: foo
b:
p1: foo
p2: bar
Using the following code:
var ds = new Deserializer();
var d = ds.Deserialize<D>(reader);
Surprisingly, I found that:
d.InputB.P1 == null
This will work fine in JSON (although I have only used Jackson in Java). Is this simply not supported or am I missing something?

Related

Automapper: map an anonymous/dynamic type

I need some help to map an anonymous object using Automapper. The goal is combine Product and Unity in a ProductDto (in which unity is a product's property).
Autommaper CreateMissingTypeMaps configuration is set to true.
My Classes:
public class Product
{
public int Id { get; set; }
}
public class Unity
{
public int Id { get; set; }
}
public class ProductDto
{
public int Id { get; set; }
public UnityDto Unity{ get; set; }
}
public class UnityDto
{
public int Id { get; set; }
}
Test Code
Product p = new Product() { Id = 1 };
Unity u = new Unity() { Id = 999 };
var a = new { Product = p, Unity = u };
var t1 = Mapper.Map<ProductDto>(a.Product);
var t2 = Mapper.Map<UnityDto>(a.Unity);
var t3 = Mapper.Map<ProductDto>(a);
Console.WriteLine(string.Format("ProductId: {0}", t1.Id)); // Print 1
Console.WriteLine(string.Format("UnityId: {0}", t2.Id)); // Print 999
Console.WriteLine(string.Format("Anonymous ProductId: {0}", t3.Id)); // Print 0 <<< ERROR: It should be 1 >>>
Console.WriteLine(string.Format("Anonymous UnityId: {0}", t3.Unity.Id)); // Print 999
There are two maps added to the profile:
CreateMap<Product, ProductDto>();
CreateMap<Unity, UnityDto>();
The problem is how Automapper map anonymous objects. I haven't time to check out Automapper source code but I got the desired behaviour with minor changes on my anonymous object:
var a = new { Id = p.Id, Unity = u };
By doing this, I might even delete previous mappings because now it is using only CreateMissingTypeMaps.
Note: As matter of fact I'm not sure if it is really an issue or I it was just my unreal expectations.

Contra variance with interfaces

I have an interface iExportColumn and a class ExportColumn implementing the interfce. ExportColumnCollection class should be generic for all the classes that implements IExportColumn interface.
public interface IExportColumn
{
string Header { get; set; }
string ColumnName { get; set; }
}
public class ExportColumn : IExportColumn
{
public ExportColumn(){}
public string Header { get; set; }
public string ColumnName { get; set; }
}
public class ExportColumnCollection<T> where T: IExportColumn
{
private List<T> cols;
public ExportColumnCollection (List<T> c)
{
cols = c;
}
public T Columninfo (string colname)
{
}
.....
}
I am getting run time error saying could not load type ExportColumnCollection.
I am looking for something to achieve somthing like
List<IExportColumn> = new List<ExportColumn>();
I have two classes implementing the interfaces IExportColumn and I need to hold a GenericCollection to handle List
The proper usage for your class would be:
List<IExportColumn> list= new List<IExportColumn>();
// you may add to the collection any class which implements IExportColumn
list.Add(new ExportColumn1() { ColumnName = "Id" });
list.Add(new ExportColumn2() { ColumnName = "Value" });
ExportColumnCollection<IExportColumn> collection = new
ExportColumnCollection<IExportColumn>(list);
var colInfo = collection.ColumnInfo("Id");

Initializing Nested strongly typed objects in LINQ to Entities

Consider this Example
public class FooWrapper
{
public FooWrapper() { }
public Foo FooObject { get; set; }
public Bar BarObject { get; set; }
}
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (
from f in _entities.FooSet
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper
{
FooObject = f,
BarObject = b
});
return results;
}
what if my Foo type class has Properties like
public class Foo(){
FProperty1{get; set;}
FPorperty2{get; set;}
}
public class Bar(){
BProperty1{get; set;}
BProperty2{get; set;}
}
and now i want to initialize my object in query like this
select new FooWrapper
{
FooObject.FProperty1 = f,
BarObject.BProperty2 = b
});
can I do this?
How will this work?
What you want is:
select new FooWrapper
{
FooObject = new Foo { FProperty1 = f },
BarObject = new Bar { BProperty2 = b }
});

Automapper and Custom Type Converter with Parent/Child

How can I covert am object to a certain type based on a property of the parent object holding the current object with automapper?
Below I have a class that contains a property called Type of enum type EventAssetType. I want to convert the property Asset to a type called DocumentModel or ImageModel that both inherit from AssetModel by using the Type property. Right now it is just mappering from Asset to AssetModel.
public class EventAssetModel
{
public EventAssetModel()
{
Event = new EventModel();
Asset = new DocumentModel();
Type = Enums.EventAssetType.Other;
}
public int Id { get; set; }
public bool Active { get; set; }
public Enums.EventAssetType Type { get; set; }
public EventModel Event { get; set; }
public AssetModel Asset { get; set; }
}
One way to accomplish this is the ConvertUsing extension method when creating a map. I've included an example for you below:
namespace Some.Namespace
{
class Program
{
static void Main(string[] args)
{
Mapper.CreateMap<Source, Animal>().ConvertUsing(MappingFunction);
Source animal = new Source() {Type = Source.SourceType.Animal, Name = "Some Animal"};
Source dog = new Source() {Type = Source.SourceType.Dog, Name = "Fido"};
Animal convertedAnimal = Mapper.Map<Source, Animal>(animal);
Console.WriteLine(convertedAnimal.GetType().Name + " - " + convertedAnimal.Name);
// Prints 'Animal - Some Animal'
Animal convertedDog = Mapper.Map<Source, Animal>(dog);
Console.WriteLine(convertedDog.GetType().Name + " - " + convertedDog.Name);
// Prints 'Dog - Fido'
}
private static Animal MappingFunction(Source source)
{
switch (source.Type)
{
case Source.SourceType.Animal:
return new Animal() {Name = source.Name};
case Source.SourceType.Dog:
return new Dog() {Name = source.Name};
}
throw new NotImplementedException();
}
}
public class Source
{
public enum SourceType
{
Animal,
Dog
}
public string Name { get; set; }
public SourceType Type { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
public class Dog : Animal
{
// Specific Implementation goes here
}
}

AutoMapper failing to map a simple list

I have used automapper for mapping lists in the past, for for some reason it won't work in this case.
public class MyType1 {
public int Id { get; set; }
public string Description { get; set; }
}
public class MyType2 {
public int Id { get; set; }
public string Description { get; set; }
}
public void DoTheMap() {
Mapper.CreateMap<MyType2, MyType1>();
Mapper.AssertConfigurationIsValid();
var theDto1 = new MyType2() { Id = 1, Description = "desc" };
var theDto2 = new MyType2() { Id = 2, Description = "desc2" };
List<MyType2> type2List = new List<MyType2> { theDto1, theDto2 };
List<MyType1> type1List = Mapper.DynamicMap<List<MyType1>>(type2List);
//FAILURE. NO EXCEPTION, BUT ZERO VALUES
List<MyType1> type1List2 =type2List.Select(Mapper.DynamicMap<MyType1>).ToList();
//SUCCESS, WITH LINQ SELECT
}
Change this:
Mapper.DynamicMap<List<MyType1>>(type2List)
To this:
Mapper.Map<List<MyType1>, List<MyType2>>(type2List);
DynamicMap is only if you don't know the type at compile time - for things like anonymous types.

Resources