How to export and import properity settings of a tool.

c#chris

Member
Joined
Dec 10, 2024
Messages
24
Programming Experience
1-3
Hello,

I want to implement a function in c#, that writes the settings of all public properties of all classes into a json file, so that the file can also be imported at other locations for restoring the properties.

Do you have some hints how to start here ?

Best regards
 
Ok, now I can serialize and deserialize single objects.
Since I have several objects and do just want to use one single JSON file, what would be the recommendation here ?

AND:
If I have a JSON file with multiple objects, will the Deserielizer be able to find the right one ?

When I setialize "this" I get a huge JSON file with nested objects, not sure if I can "JsonConvert.Deserialize" specific objects from that file.
 
Last edited:
I tried it with a list of objects because each object is derived from a different class -> List<object> = objectlist new();
It generates a JSON file of the format: [{...},{...},{...}].
But when I deserialize the objects in the list I need to cast each object the apporopiate classes, here I am getting errors.
test 1 = (Class1) objectlist[0];
test 2 = (Class2) objectlist[1];
test 3 = (Class3) objectlist[3];
etc.

Am I on the right path ?
 
Easiest way is to have a "container" class which has a bunch of properties with references to the objects you want to serialize so that when you deserialze, they are all the right type already.

Your casting above won't work because the JSON does not include the object types, so when the deseriallization happens it does not know what kind of object to instantiate.
 
Ok, I created a Container like this:

C#:
[DataContract]
internal class MyContainer
{
    [DataMember]
    internal MyTextSettings? contTextSettings { get; set; }
    [DataMember]
    internal MyVwap2? contVwap2 { get; set; }

}

I fill the container like this (Setter DI).

C#:
 myContainer = new()
        {
            //Setter DI
            contTextSettings = MyTextSettings,
            contVwap2 = MyVwapDaily
        };

I serialize like this:

C#:
 var sentinelJSON = JsonConvert.SerializeObject(myContainer, Newtonsoft.Json.Formatting.Indented, settings);

I deserialize like this:

C#:
 if (myContainer != null)
                {
                    myContainer = JsonConvert.DeserializeObject<MyContainer>(_jsonFileRead, settings);
                    //MyTextSettings = myContainer.contTextSettings;
                    //MyVwapDaily = myContainer.contVwap2;
                }

My expectation now would be that the opbjects are updated automatically, if I e.g. make amendments in JSON file before Deserialization.
Why: Becaus e according to my understanding I linked the container objects and the dll objects via setter DI (like pointers in c).

But: Nothing happens.

When I uncomment the commented code it works.
Could you pls. comment this ?
Is the a way for autoupdating without the commented code.
 
Recall that in C# all object classes are by reference, rather than by value in C/C++. So when you do the assignment on your commented lines, all that happens is that variables MyTextSettings and MyVwapDaily now point to the instances that you deserialized. But the rest of your code in still pointing to the old objects prior to changing the pointer. The values within those old objects are not updated by the assignment.
 
Last edited:
Do I have to reassign event handlers ?

C#:
[CODE=csharp] if (myContainer != null)

                {

                    myContainer = JsonConvert.DeserializeObject<MyContainer>(_jsonFileRead, settings);

                    MyTextSettings = myContainer.contTextSettings;

                    MyVwapDaily = myContainer.contVwap2;

                }
[/CODE]


The Classes MyTextSetting etc. contain events and the plugin dll which uses these classes have subscribed to these evetns.
It seems that after all that serialization and deserialization via MyTextSettings = myContainer.contTextSettings etc. I need
tu reassign the eventhandlers, otherwise it does not work as expected.

But:
When I do that I see that the events have been subscribed two times, which also makes no sense from my point of view.
Any advice on how to handle that in a correct way ?
 
I know of no serializers which serialize and deserialize event handlers and delegates. Think about it. How would a serializer know which object contains the event handler? Specific to the JSON (and XML) serializer/deserializer: How would it store that type information in JSON? How would a it know how to re-instantiate that object on deserialization if it doesn't know the type?

So yes, you would need to re-assign the event handlers.

How did you determine that the particular instance of MyTextSettings and MyVwapDaily have been subscribed to twice?

Personally, I think it more likely that two event handlers were created, but they are subscribed to two different instances.

Theoretically somewhere in your code you have something like this because you didn't follow advice on post #8:
C#:
MyTextSettings = new TextSettings();

And you have either:
Case A:
C#:
MyTextSettings.Click += new EventHandler(Foo.OnClick);
or
Case B:
C#:
class TextSettings
{
    public TextSettings()
    {
        Click += new EventHandler(Foo.OnClick);
    }
}

And then later you have your code from post #21:
C#:
if (myContainer != null)
{
    // The DeserializeObject() call below will create new instances of TextSettings
    myContainer = JsonConvert.DeserializeObject<MyContainer>(_jsonFileRead, settings);

    // Now you are pointing to that new instance:
    MyTextSettings = myContainer.contTextSettings;
    :
}

If you had case B, then as part of the calling the constructor for TextSettings, a new Click event handler will created.

If you had case A: you would need something like:
C#:
if (myContainer != null)
{
    // The DeserializeObject() call below will create new instances of TextSettings
    myContainer = JsonConvert.DeserializeObject<MyContainer>(_jsonFileRead, settings);

    // Now you are pointing to that new instance:
    MyTextSettings = myContainer.contTextSettings;
    MyTextSettings.Click += new EventHandler(Foo.OnClick);
    :
}

In both Case A and Case B, they will be new instances of TextSettings. They won't be the old instance you originally had when you first had:
C#:
MyTextSettings = new TextSettings();
 
How did you determine that the particular instance of MyTextSettings and MyVwapDaily have been subscribed to twice?

I use:

C#:
public int SubscriberClients()
{
       return PropertyChanged == null ? 0 : PropertyChanged.GetInvocationList().Length;
    }

as a member function e.g. in "TextSettings" and so I cann see before and after deserialization the number of subscriptions to a particular event handler. Before: 1, After: 2.
 
How did your get the instance of the object before it was deserialized to call SubscriberClients() ?
 
Also, is there any chance you declared the event PropertyChanged as static?
 
Hello, I did the following:

During start of my dll, I do the subscriptions:

TextSettings.PropertyChanged += OnChangeProperty

C#:
protected override void OnChangeProperty([CallerMemberName] string propertyName = "")
    {
//do sth

        base.OnChangeProperty(propertyName);
    }



When I check TextSettings after that, but before serialization: TextSettings.SubscriberClients() -> 1

After Serialization/Deserialisation I use:

MyTextSettings = myContainer.contTextSettings; -> Code does not work as expected, seems that eventhandling is missing, properties are fine.

When I use the following statement again:

TextSettings.PropertyChanged += OnChangeProperty-> Code works.

When I check TextSettings after all of that: TextSettings.SubscriberClients() -> 2

According to my understanding TextSettings.SubscriberClients() should be 1 again, otherwise with each deserialization the number would increase endlessly.

Propertychanged is not static.
 
With the following statement after deserialization code works and I have no increasing subscription:

TextSettings.PropertyChanged -= OnChangeProperty
TextSettings.PropertyChanged += OnChangeProperty

But still I do not understand the underlying mechanics.
 
That is really strange. I know that you have a big large complicated app, but if there is a way to make a minimal repro case where you can post all the code, the would help a lot.
 
Back
Top Bottom