Reputation: 61
config.yaml:
App1:
settings:
redirectUrl: http://www.test.com
App2:
settings:
redirectUrl:
test: http://www.test.com
prod: http://www.prod.com
C# objects
public class Config
{
public Dictionary<string, App> Apps { get; set; }
}
public class App
{
public Dictionary<string, Setting> Settings { get; set; }
}
public class Setting
{
public string Test {get;set;}
public string Prod {get;set;}
}
Expected result:
for App1
, both test
and prod
are the same http://www.test.com
for App2
, test
is http://www.test.com
and prod
is http://www.prod.com
I have done a lot of research but cannot figure out how to achieve this by using custom deserializer. Please help..
Upvotes: 2
Views: 2634
Reputation: 12469
You could make your Settings
class implement IYamlConvertible
. That interface allows you to control the serialization process. A possible implementation could be:
public class SettingsBase
{
public string Test { get; set; }
public string Prod { get; set; }
}
public class Setting : SettingsBase, IYamlConvertible
{
public void Read(IParser parser, Type type, ObjectDeserializer nestedObjectDeserializer)
{
var scalar = parser.Allow<Scalar>();
if (scalar != null)
{
Test = Prod = scalar.Value;
}
else
{
var values = (SettingsBase)nestedObjectDeserializer(typeof(SettingsBase));
this.Test = values.Test;
this.Prod = values.Prod;
}
}
public void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer)
{
if (Test == Prod)
{
nestedObjectSerializer(Test);
}
else
{
nestedObjectSerializer(new SettingsBase { Test = this.Test, Prod = this.Prod });
}
}
}
Here I've used a base class (SettingsBase
) as a way to easily (de)serialize the properties, but one could use another strategy. Basically the Read
method checks if the current token is a scalar. If so, it uses its value. Otherwise, it deserializes as a SettingsBase
. The Write
method does the opposite.
A fully working example is available here
Upvotes: 2