opened
perturbare
username_0
This pull request contains a set of changes I made for my own project that uses GraphX. With these changes, the serialization is further decoupled from the LogicCore and GraphArea to make it easier to use other storage types. In my case, I needed to use streams.

Please note: I apologize, but my development environment is Windows 7, so I cannot update the METRO assemblies at this time. If you like these changes, I think you'll find the conversion to be pretty trivial, but I have not messed with those because I cannot test them yet.

In GraphArea, I've changed SerializeToFile and DeserializeFromFile into methods that return or accept the collections of graph data. This makes the GraphArea serialization support more widely usable and allows developers to make use of other storage types without having to extend GraphArea.

The FileServiceProvider property is removed from LogicCore. This removes the file specific dependencies from LogicCore and supports the goal of using other storage types without having to add more provider types to LogicCore.

The IFileServiceProvider interface has been removed. It certainly does not have to be deleted, but it's not necessary to have a common interface for serialization.

FileServiceProviderWpf has been altered in a few ways. The IFileServiceProvider interface goes away. It is converted to a static class because no instance information is needed in it and the calling sites don't need to create an instance. Stream serialization is added for the sake of providing an example (this is the key piece I needed in my project).

GeneralGraph is changed to show how the FileServiceProviderWpf class is used with the changes to GraphArea.

I am open to suggestions, so please let me know your thoughts. This would be a breaking change for some users of GraphX, but I hope you'll find the value of decoupling from file specific I/O is worth the change. Again, I apologize for not being able to provide the METRO updates with this request.

Thanks.

Jon
Serialization decoupling
issue
created
panthernet
username_1
Thanks, i think you're right. All the GraphX need to do in this case is to supply serialization data and leave the serialization details to custom code.
comment
created
birbilis
username_2
Using static classes instead of interfaces can mean though that you need to use reflection to call them (e.g. if you wan to have a list of export plugins). 

Instead can keep interfaces and make use of MEF to locate import/export and other plugins (you can have some class attribute there that mark the class as a GraphXExporter and MEF can be asked then to give you interface instances from classes that have that attribute.)

see usage at
http://clipflair.codeplex.com/SourceControl/latest#Client/ClipFlair.Windows/ClipFlair.Windows.Map/MapWindowFactory.cs
and
http://clipflair.codeplex.com/SourceControl/latest#Client/ClipFlair.Windows/ClipFlair.Windows.Image/ImageWindowFactory.cs

----------

﻿//Project: ClipFlair (http://ClipFlair.codeplex.com)
//Filename: MapWindowFactory.cs
//Version: 20140318

using System.ComponentModel.Composition;

namespace ClipFlair.Windows.Map
{

  //Supported views
  [Export("ClipFlair.Windows.Views.MapView", typeof(IWindowFactory))]
  //MEF creation policy
  [PartCreationPolicy(CreationPolicy.Shared)]
  public class MapWindowFactory : IWindowFactory
  {
    public BaseWindow CreateWindow()
    {
      return new MapWindow();
    }
  }

}

----------

//Project: ClipFlair (http://ClipFlair.codeplex.com)
//Filename: ImageWindowFactory.cs
//Version: 20140616

using System.ComponentModel.Composition;
using System.IO;

namespace ClipFlair.Windows.Image
{

  //Supported file extensions
  [Export(".PNG", typeof(IFileWindowFactory))]
  [Export(".JPG", typeof(IFileWindowFactory))]
  //Supported views
  [Export("ClipFlair.Windows.Views.ImageView", typeof(IWindowFactory))]
  //MEF creation Policy
  [PartCreationPolicy(CreationPolicy.Shared)]
  public class ImageWindowFactory : IFileWindowFactory
  {

    public const string LOAD_FILTER = "Image files (*.png, *.jpg)|*.png;*.jpg";

    public static string[] SUPPORTED_FILE_EXTENSIONS = new string[] { ".PNG", ".JPG" };

    public string[] SupportedFileExtensions()
    {
      return SUPPORTED_FILE_EXTENSIONS;
    }

    public BaseWindow CreateWindow()
    {
      return new ImageWindow();
    }

  }

}

then at 
http://clipflair.codeplex.com/SourceControl/latest#Client/ClipFlair.Windows/ClipFlair.Windows.Base/Source/View/BaseWindow.xaml.cs

to get the first plugin that supports some contract (I get that contract name from the serialization file [using DataContracts]) for a loaded view, or that supports some file extension for a file dropped inside a component, I do:

    protected static IWindowFactory GetWindowFactory(string contract)
    {
      Lazy<IWindowFactory> win = mefContainer.GetExports<IWindowFactory>(contract).FirstOrDefault();
      if (win == null)
        throw new Exception(BaseWindowStrings.msgUnknownViewType + contract);
      else
        return win.Value;
    }

    protected static IFileWindowFactory GetFileWindowFactory(string contract)
    {
      Lazy<IFileWindowFactory> win = mefContainer.GetExports<IFileWindowFactory>(contract).FirstOrDefault();
      if (win != null)
        return win.Value;
      else
        return null;
    }
comment
created
perturbare
username_0
The class I converted to static is in the sample application. It does not have to be static, but it was a reasonable conversion for the sample. In a case such as yours, you are free to define an interface and build many serializers that implement it. That added flexibility is a benefit of this set of changes.
comment