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 }