Pull Requests - serialization

Topics: Windows Forms
Oct 1, 2010 at 4:50 PM

I placed a pull request a considerable amount of time ago, which was either rejected/or expired.

I've placed another one.... But basically I want to know how I can get the code I wrote incorporated into the main trunk?

Oct 1, 2010 at 5:25 PM

yes i see it, the serializable stuff, maybe it's time for review, nothing is rejected!

Oct 1, 2010 at 5:30 PM
Edited Oct 1, 2010 at 5:32 PM

...there was some changes, i don't know if they are in sync with your fork, can you test it if it still works with latest changeset? This stuff will add some maintenance to be in sync between wpf/forms/mobile, i can't just simply 'apply' it, you know ;}

p.s. unless someone provides a complete solution {;

Oct 5, 2010 at 7:55 AM

radioman, 

I understand that they can just be applied, I'll take a look and let you know if it still works. I believe it's a useful extension however (to be able to save and reload overlays).

I'll get back to you as soon as I can.

Oct 10, 2010 at 4:37 PM

radioman. 

I've had a quick look at trying to check if things are in sync, but I can't figure out how to synchronize my fork with the main branch to check. Do you know how to do this?

Oct 10, 2010 at 5:13 PM
Edited Oct 10, 2010 at 5:16 PM

fork default branch locally, then push your codeplex fork to that local default fork ;/

..well, i can't explain it exactly ;}

Oct 11, 2010 at 12:42 PM

Would it be easier if I just get all my changes together, create a new fork then send a pull request on that one instead? Then the old one could be deleted after...

Oct 11, 2010 at 1:07 PM

yeah, you can try that

Oct 11, 2010 at 1:20 PM

radioman. I just uplifted all the changes, all builds ok (just had to make a few minor tweaks) so should be good. I've done the pull request. This currently is for winforms only (I don't know a whole lot about WPF yet but I'll look at what needs to be done to replicate it in WPF and then hopefully create another Fork once I know what I'm doing.

Oct 11, 2010 at 1:47 PM

ok, i'll try to merge it in, different formating makes hard to see real changes...

Oct 11, 2010 at 1:50 PM

Thanks radioman. I can go through make sure you've got all the changes once your done. Apart from the GMapControl most of the changes are an implementation of ISerializable (and possibly IDeserializationCallback) with their methods inside an appropriate auto generated region by VS2010 (e.g. #region ISerialization Members) so it shouldn't be too bad to spot the changes.

Oct 11, 2010 at 1:52 PM

p.s. you missed to add Extensions.cs, and to use extensions in core isn't very good, because it's based on .net2, hmm..

Oct 11, 2010 at 1:56 PM
Edited Oct 11, 2010 at 1:56 PM

hmm, I'll have a quick look. 

Extension methods are supported in .net 2.0. They just missed it out of the compiler, but I added in the standard fix to enable this. Here's the code if you want to just do a copy n' paste to add it in. With the ExtensionAttribute you can then use extensions wherever you fancy and it'll work just fine.

 

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// Allows the use of Extension methods within .NET 2.0 Build.
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class ExtensionAttribute : Attribute
    {
    }
}

namespace GMap.NET
{
    public static class Extensions
    {
        /// <summary>
        /// Retrieves a value from the SerializationInfo of the given type.
        /// </summary>
        /// <typeparam name="T">The Type that we are attempting to de-serialize.</typeparam>
        /// <param name="info">The SerializationInfo.</param>
        /// <param name="key">The key of the value we wish to retrieve.</param>
        /// <returns>The value if found, otherwise null.</returns>
        public static T GetValue<T>(this SerializationInfo info, string key) where T : class
        {
            // Return the value from the SerializationInfo, casting it to type T.
            return info.GetValue(key, typeof(T)) as T;
        }

        /// <summary>
        /// Retrieves a value from the SerializationInfo of the given type.
        /// </summary>
        /// <typeparam name="T">The Type that we are attempting to de-serialize.</typeparam>
        /// <param name="info">The SerializationInfo.</param>
        /// <param name="key">The key of the value we wish to retrieve.</param>
        /// <param name="defaultValue">The default value if the de-serialized value was null.</param>
        /// <returns>The value if found, otherwise the default value.</returns>
        public static T GetValue<T>(this SerializationInfo info, string key, T defaultValue) where T : class
        {
            T deserializedValue = info.GetValue<T>(key);
            if (deserializedValue != null)
            {
                return deserializedValue;
            }

            return defaultValue;
        }

        /// <summary>
        /// Retrieves a value from the SerializationInfo of the given type for structs.
        /// </summary>
        /// <typeparam name="T">The Type that we are attempting to de-serialize.</typeparam>
        /// <param name="info">The SerializationInfo.</param>
        /// <param name="key">The key of the value we wish to retrieve.</param>
        /// <param name="defaultValue">The default value if the de-serialized value was null.</param>
        /// <returns>The value if found, otherwise the default value.</returns>
        public static T GetStruct<T>(this SerializationInfo info, string key, T defaultValue) where T : struct
        {
            try
            {
                return (T)info.GetValue(key, typeof(T));
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }
    }
}

 

Oct 11, 2010 at 2:00 PM

good, but g, why do people invented forks... To forget copy/paste/add new file/save ;} can you just add this file and push it?

Oct 11, 2010 at 2:02 PM

Yeah, I have done now. Sorry.

Oct 11, 2010 at 2:53 PM

I see what you mean about the formatting changes now I've seen your changes. Sorry about that. Our VS IDE's must be set up differently...

Oct 11, 2010 at 3:57 PM
Edited Oct 11, 2010 at 5:01 PM

anyway it's done, thank You! ;}

p.s. i've found a way, tortoisemerge has option to ignore formating, perfect!

Oct 11, 2010 at 5:08 PM

Thanks radioman, and no problem. It's great to have the chance to contribute to a really good project.


That probably is useful in tortoisemerge. My VS2010 formats stuff like that automatically, although I do have to sayit is an odd layout choice you've chosen (never seen anything quite like it).

Oct 11, 2010 at 5:29 PM

what do you mean 'odd'? ;}

Oct 28, 2010 at 3:51 PM

Hello guys.  Great work adding serialization to the layers.

However, by adding this code...

namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// Allows the use of Extension methods within .NET 2.0 Build.
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class ExtensionAttribute : Attribute
    {
    }
}

...we allow extension methods to exist in the .NET 2.0 library, but we also disallow extension methods in the implementing application when the application uses a later version, say, .NET 3.5 or .NET 4.0.  

Last night, I updated to the latest sources (to get the MouseWheelIgnoreMarkers feature), and my extension methods in my 4.0 application cannot coexist with the new extension methods in GMap.  It has to do with System.Runtime.CompilerServices.ExtensionAttribute having multiple definitions.

Does anybody know of an elegant solution to this problem?  I've been working at it for a few hours, but have not had much luck.

 

Thanks! 

 

Oct 28, 2010 at 6:03 PM

hm, so i guess by default we need disable it

Oct 28, 2010 at 8:32 PM
Edited Oct 28, 2010 at 8:37 PM

Hmm, that's annoying...


mattgerg, the best way to handle this then is via a refactor. Extension methods are just an easy of use, there's no reason that they really need to be there, other than making the code nicer. We could either wrap the extension attribute in an if like below:

 

#if NETVersion20

/// <summary>
/// Allows the use of Extension methods within .NET 2.0 Build.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ExtensionAttribute : Attribute { }

#endif

 

This way anyone wanting to use it would have to define the NETVersion20 in their project settings. Other alternatives are that it doesn't support .NET 2.0 (I'm not sure what the target platform is, radioman would have to confirm that), or otherwise to not use extension attributes for the serialization which adds a bit of overhead. Easiest way to remove the extension attributes is to target .NET 2.0, remove the class with that definition and change all the calls (I can't remember the method used off the top of my head) from:

classInstance.Method(obj1)
// to
Method(classInstance, obj1)

This should also get around the problem. I probably can't make the changes for a little while so feel free to do so yourself. If not if you can wait a little I'll take a look. 

Nov 3, 2010 at 9:51 PM
Edited Nov 3, 2010 at 9:52 PM

Thanks for the reply, Ian.

If we were to take the preprocessor approach, anyone who wanted to use serialization in .NET 2.0 would have to define NETVersion20, not in their project, but in GMap.NET itself; the directives affect the code during compilation, so by the time we include a GMap.NET DLL, in a project, it is already too late for preprocessor.  Right?

Correct me if I am wrong, radioman, but the library itself targets .NET 2.0, so the project will not build without the ExtensionAttribute() class at this point.  Further to this, I have tried to build the library for .NET 4.0 and .NET 3.5, but the map tiles do not render when the target platform has been updated.

For these reasons, I think the simplest solution would be to rewrite serialization using static methods rather than extensions.  Its not as pretty from the code's point of view, but that solution involves no hackery.  We keep serialization, target platform remains unchanged, and the library continues to work for everybody as is.

 

Radioman, Ian, your thoughts?

Nov 3, 2010 at 10:14 PM

i guess you are right

Dec 16, 2010 at 1:01 PM

Are there some developments regarding Serialization?

I want to print (and save as wmf). PrintVisual complaints about different threads owns it (I also tried creating a deep clone using XamlWriter, but same problem).

Radioman: maybe you can add a Print method in the WPF. Something like:

public void Print()
        {
            PrintDialog dlg = new PrintDialog();
            dlg.PageRangeSelection = PageRangeSelection.AllPages;
            dlg.UserPageRangeEnabled = true;
            if (dlg.ShowDialog().Value)
                dlg.PrintVisual(MainMap, "Map");
        }

Dec 16, 2010 at 1:47 PM

Serialization stuff is solved, but just for windows forms version, i doubt you can clone wpf visuals...

Dec 16, 2010 at 2:40 PM

I don't know if cloning is always possible (at least you should have a parameter-less constructor for each class). But I did it a couple of times.

This is a technique of cloning:

 
// Clone Map
string mapXaml = XamlWriter.Save(MainMap);

StringReader stringReader = new StringReader(mapXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
GMapControl dupMap = (GMapControl)XamlReader.Load(xmlReader);

I tried it and I ran into the problem that some of your variables have a name that is used elsewhere as well. My application had simular problems in the past; you can rename the variable (easiest) or give directions to the serializer.

But if you add the Print() command there is, for me, no need for serialization. I like to (have it to) create a WMF, but PNG is good enough.

 

Dec 17, 2010 at 8:58 AM

Are you sure you need to be cloning stuff? You've not mentioned much about the problem you're having but sounds kinda like UI/multi-threading issues? 

Dec 17, 2010 at 10:18 AM

Hi Ian,

No I don't need cloning stuff per se. I want to Print (and export to WMF). But this is WPF (not WinForms).

I also thought about threading issues as I received the famous "The calling thread cannot access this object because a different thread owns it". But if you use the Print method I posted above in the Demo, it will print ok if you only have markers. If you have a map, the same threading error pops up. That's why I tried to create a clone.