protected static T GetInstance <T>() where T : DataProcessor
        {
            //this forces helper static constructor to be called and gets us an instance if composition worked
            var instance = DPSManager.GetDataProcessor <T>() as T;

            if (instance == null)
            {
                //if the instance is null the type was not added as part of composition
                //create a new instance of T and add it to helper as a compressor
#if NETFX_CORE
                var construct = (from constructor in typeof(T).GetTypeInfo().DeclaredConstructors
                                 where constructor.GetParameters().Length == 0
                                 select constructor).FirstOrDefault();
#else
                var construct = typeof(T).GetConstructor(new Type[] { });
                if (construct == null)
                {
                    construct = typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
                }
#endif
                if (construct == null)
                {
                    throw new Exception();
                }

                instance = construct.Invoke(new object[] { }) as T;

                DPSManager.AddDataProcessor(instance);
            }

            return(instance);
        }
        private DPSManager()
        {
            //This constructor loops through referenced assemblies looking for types that inherit off of DataSerializer and
            //DataProcessor.  On windows this should mean perfect auto detection of serializers and compressors. On windows
            //phone we cannot get a list of referenced assemblies so we can only do this for already loaded assemblies.
            //Any others that are used will have to be added manually.  On windows this will be done from a new app domain
            //so we can unload it afterwards

            //This action will perform the load in the background on some client dependent "thread"
            Action loadAction = new Action(() =>
            {
                //Initialise the core extensions
                DPSManager.GetDataSerializer <ExplicitSerializer>();
                DPSManager.GetDataSerializer <NullSerializer>();
                DPSManager.GetDataProcessor <DataPadder>();
#if !FREETRIAL
                //Only the full version includes the encrypter
                DPSManager.GetDataProcessor <RijndaelPSKEncrypter>();
#endif

#if !WINDOWS_PHONE && !NETFX_CORE
                DPSManager.GetDataSerializer <BinaryFormaterSerializer>();
#endif

                AssemblyLoader loader;
                ProcessArgument args;

#if !WINDOWS_PHONE && !iOS && !ANDROID && !NETFX_CORE
                AppDomain tempDomain = null;

                try
                {
                    //Create a new domain with the same settings as the current domain
                    AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
                    tempDomain           = AppDomain.CreateDomain("Temp_" + Guid.NewGuid().ToString(), AppDomain.CurrentDomain.Evidence, setup);

                    try
                    {
                        //First try creating the proxy from the assembly using the assembly name
                        loader = (AssemblyLoader)tempDomain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.FullName, typeof(AssemblyLoader).FullName);
                    }
                    catch (FileNotFoundException)
                    {
                        //If that fails try with the assembly location.  An exception here
                        loader = (AssemblyLoader)tempDomain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName);
                    }

                    args = new ProcessArgument();

                    //If an entry assembly exists just pass that, the rest can be worked out from there.
                    //On WCF there is no entry assembly. In that case fill the loaded domains list with those already loaded
                    if (Assembly.GetEntryAssembly() != null)
                    {
                        args.loadedDomains = new List <string>()
                        {
                            Assembly.GetEntryAssembly().FullName
                        }
                    }
                    ;
                    else
                    {
                        List <string> loadedDomains = new List <string>();

                        foreach (var ass in AppDomain.CurrentDomain.GetAssemblies())
                        {
                            loadedDomains.Add(ass.FullName);
                        }

                        args.loadedDomains = loadedDomains;
                    }

                    loader.ProcessApplicationAssemblies(args);
                }
                catch (FileNotFoundException)
                {
                    //In mono, using mkbundle, the above load method may not work so we will fall back to our older way of doing the same
                    //The disadvantage of this approach is that all assemblies are loaded and then stay in memory increasing the footprint slightly
                    loader = new AssemblyLoader();
                    args   = new ProcessArgument();

                    loader.ProcessApplicationAssemblies(args);
                }
                catch (MissingMethodException)
                {
                    loader = new AssemblyLoader();
                    args   = new ProcessArgument();

                    loader.ProcessApplicationAssemblies(args);
                }
                catch (Exception)
                {
                    loader = new AssemblyLoader();
                    args   = new ProcessArgument();

                    loader.ProcessApplicationAssemblies(args);
                }
                finally
                {
                    if (tempDomain != null)
                    {
                        try
                        {
                            AppDomain.Unload(tempDomain);
                        }
                        catch (Exception) { }
                        finally
                        {
                            tempDomain = null;
                            GC.Collect();
                        }
                    }
                }
#else
                loader = new AssemblyLoader();
                args   = new ProcessArgument();

                loader.ProcessApplicationAssemblies(args);
#endif
                foreach (var serializer in args.serializerTypes)
                {
                    lock (addRemoveObjectLocker)
                    {
                        if (!SerializersByType.ContainsKey(serializer.Value))
                        {
                            SerializersByType.Add(serializer.Value, null);
                            DataSerializerIdToType.Add(serializer.Key, serializer.Value);
                        }
                    }
                }

                foreach (var processor in args.processorTypes)
                {
                    lock (addRemoveObjectLocker)
                    {
                        if (!DataProcessorsByType.ContainsKey(processor.Value))
                        {
                            DataProcessorsByType.Add(processor.Value, null);
                            DataProcessorIdToType.Add(processor.Key, processor.Value);
                        }
                    }
                }

                loadCompleted.Set();
            });

#if NET2 || NET35
            Thread loadThread = new Thread(new ThreadStart(loadAction));
            loadThread.Name = "DPS load thread";
            loadThread.Start();
#else
            Task.Factory.StartNew(loadAction);
#endif
        }