Browse Source

complete .net core support

Luke Pulverenti 8 years ago
parent
commit
67c6d0fd8f

+ 125 - 14
Emby.Common.Implementations/BaseApplicationHost.cs

@@ -32,6 +32,9 @@ using MediaBrowser.Common.IO;
 using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.System;
 using MediaBrowser.Model.Tasks;
+#if NETSTANDARD1_6
+using System.Runtime.Loader;
+#endif
 
 namespace Emby.Common.Implementations
 {
@@ -173,11 +176,25 @@ namespace Emby.Common.Implementations
 
         public virtual string OperatingSystemDisplayName
         {
-            get { return Environment.OSVersion.VersionString; }
+            get
+            {
+#if NET46
+                return Environment.OSVersion.VersionString;
+#endif
+#if NETSTANDARD1_6
+                return System.Runtime.InteropServices.RuntimeInformation.OSDescription;
+#endif
+                return "Operating System";
+            }
         }
 
         public IMemoryStreamProvider MemoryStreamProvider { get; set; }
 
+        /// <summary>
+        /// The container
+        /// </summary>
+        protected readonly SimpleInjector.Container Container = new SimpleInjector.Container();
+
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseApplicationHost{TApplicationPathsType}"/> class.
         /// </summary>
@@ -284,11 +301,10 @@ namespace Emby.Common.Implementations
 
             builder.AppendLine(string.Format("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs())));
 
+#if NET46
             builder.AppendLine(string.Format("Operating system: {0}", Environment.OSVersion));
-            builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount));
             builder.AppendLine(string.Format("64-Bit OS: {0}", Environment.Is64BitOperatingSystem));
             builder.AppendLine(string.Format("64-Bit Process: {0}", Environment.Is64BitProcess));
-            builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath));
 
             Type type = Type.GetType("Mono.Runtime");
             if (type != null)
@@ -299,7 +315,10 @@ namespace Emby.Common.Implementations
                     builder.AppendLine("Mono: " + displayName.Invoke(null, null));
                 }
             }
+#endif    
 
+            builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount));
+            builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath));
             builder.AppendLine(string.Format("Application Path: {0}", appPaths.ApplicationPath));
 
             return builder;
@@ -312,7 +331,9 @@ namespace Emby.Common.Implementations
             try
             {
                 // Increase the max http request limit
+#if NET46
                 ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
+#endif    
             }
             catch (Exception ex)
             {
@@ -410,6 +431,7 @@ namespace Emby.Common.Implementations
 
                 if (assemblyPlugin != null)
                 {
+#if NET46
                     var assembly = plugin.GetType().Assembly;
                     var assemblyName = assembly.GetName();
 
@@ -420,10 +442,24 @@ namespace Emby.Common.Implementations
                     var assemblyFilePath = Path.Combine(ApplicationPaths.PluginsPath, assemblyFileName);
 
                     assemblyPlugin.SetAttributes(assemblyFilePath, assemblyFileName, assemblyName.Version, assemblyId);
+#elif NETSTANDARD1_6
+                    var typeInfo = plugin.GetType().GetTypeInfo();
+                    var assembly = typeInfo.Assembly;
+                    var assemblyName = assembly.GetName();
+
+                    var attribute = (GuidAttribute)assembly.GetCustomAttribute(typeof(GuidAttribute));
+                    var assemblyId = new Guid(attribute.Value);
+
+                    var assemblyFileName = assemblyName.Name + ".dll";
+                    var assemblyFilePath = Path.Combine(ApplicationPaths.PluginsPath, assemblyFileName);
+
+                    assemblyPlugin.SetAttributes(assemblyFilePath, assemblyFileName, assemblyName.Version, assemblyId);
+#else
+return null;
+#endif
                 }
 
                 var isFirstRun = !File.Exists(plugin.ConfigurationFilePath);
-
                 plugin.SetStartupInfo(isFirstRun, File.GetLastWriteTimeUtc, s => Directory.CreateDirectory(s));
             }
             catch (Exception ex)
@@ -451,7 +487,17 @@ namespace Emby.Common.Implementations
 
             AllConcreteTypes = assemblies
                 .SelectMany(GetTypes)
-                .Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType)
+                .Where(t =>
+                {
+#if NET46
+                    return t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType;
+#endif    
+#if NETSTANDARD1_6
+                    var typeInfo = t.GetTypeInfo();
+                    return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsInterface && !typeInfo.IsGenericType;
+#endif
+                    return false;
+                })
                 .ToArray();
         }
 
@@ -532,14 +578,38 @@ namespace Emby.Common.Implementations
         /// </summary>
         /// <param name="type">The type.</param>
         /// <returns>System.Object.</returns>
-        public abstract object CreateInstance(Type type);
+        public object CreateInstance(Type type)
+        {
+            try
+            {
+                return Container.GetInstance(type);
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error creating {0}", ex, type.FullName);
+
+                throw;
+            }
+        }
 
         /// <summary>
         /// Creates the instance safe.
         /// </summary>
         /// <param name="type">The type.</param>
         /// <returns>System.Object.</returns>
-        protected abstract object CreateInstanceSafe(Type type);
+        protected object CreateInstanceSafe(Type type)
+        {
+            try
+            {
+                return Container.GetInstance(type);
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error creating {0}", ex, type.FullName);
+                // Don't blow up in release mode
+                return null;
+            }
+        }
 
         /// <summary>
         /// Registers the specified obj.
@@ -547,30 +617,58 @@ namespace Emby.Common.Implementations
         /// <typeparam name="T"></typeparam>
         /// <param name="obj">The obj.</param>
         /// <param name="manageLifetime">if set to <c>true</c> [manage lifetime].</param>
-        protected abstract void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
-            where T : class;
+        protected void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
+            where T : class
+        {
+            Container.RegisterSingleton(obj);
+
+            if (manageLifetime)
+            {
+                var disposable = obj as IDisposable;
+
+                if (disposable != null)
+                {
+                    DisposableParts.Add(disposable);
+                }
+            }
+        }
 
         /// <summary>
         /// Registers the single instance.
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <param name="func">The func.</param>
-        protected abstract void RegisterSingleInstance<T>(Func<T> func)
-            where T : class;
+        protected void RegisterSingleInstance<T>(Func<T> func)
+            where T : class
+        {
+            Container.RegisterSingleton(func);
+        }
 
         /// <summary>
         /// Resolves this instance.
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <returns>``0.</returns>
-        public abstract T Resolve<T>();
+        public T Resolve<T>()
+        {
+            return (T)Container.GetRegistration(typeof(T), true).GetInstance();
+        }
 
         /// <summary>
         /// Resolves this instance.
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <returns>``0.</returns>
-        public abstract T TryResolve<T>();
+        public T TryResolve<T>()
+        {
+            var result = Container.GetRegistration(typeof(T), false);
+
+            if (result == null)
+            {
+                return default(T);
+            }
+            return (T)result.GetInstance();
+        }
 
         /// <summary>
         /// Loads the assembly.
@@ -581,7 +679,13 @@ namespace Emby.Common.Implementations
         {
             try
             {
+#if NET46
                 return Assembly.Load(File.ReadAllBytes(file));
+#elif NETSTANDARD1_6
+                
+                return AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(file)));
+#endif
+                return null;
             }
             catch (Exception ex)
             {
@@ -600,7 +704,14 @@ namespace Emby.Common.Implementations
         {
             var currentType = typeof(T);
 
-            return AllConcreteTypes.AsParallel().Where(currentType.IsAssignableFrom);
+#if NET46
+            return AllConcreteTypes.Where(currentType.IsAssignableFrom);
+#elif NETSTANDARD1_6
+            var currentTypeInfo = currentType.GetTypeInfo();
+
+            return AllConcreteTypes.Where(currentTypeInfo.IsAssignableFrom);
+#endif
+            return new List<Type>();
         }
 
         /// <summary>

+ 44 - 6
Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -13,7 +13,6 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
-using System.Net.Cache;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -70,11 +69,13 @@ namespace Emby.Common.Implementations.HttpClientManager
             _memoryStreamProvider = memoryStreamProvider;
             _appPaths = appPaths;
 
+#if NET46
             // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
             ServicePointManager.Expect100Continue = false;
 
             // Trakt requests sometimes fail without this
             ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
+#endif    
         }
 
         /// <summary>
@@ -131,6 +132,7 @@ namespace Emby.Common.Implementations.HttpClientManager
 
         private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options)
         {
+#if NET46
             request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) =>
             {
                 if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
@@ -139,6 +141,7 @@ namespace Emby.Common.Implementations.HttpClientManager
                 }
                 throw new InvalidOperationException("no IPv4 address");
             };
+#endif    
         }
 
         private WebRequest GetRequest(HttpRequestOptions options, string method)
@@ -165,34 +168,52 @@ namespace Emby.Common.Implementations.HttpClientManager
 
                 AddRequestHeaders(httpWebRequest, options);
 
-                httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ? 
-                    (options.DecompressionMethod ?? DecompressionMethods.Deflate) : 
+#if NET46
+                httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ?
+                    (options.DecompressionMethod ?? DecompressionMethods.Deflate) :
                     DecompressionMethods.None;
+#endif    
             }
 
-            request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
+
+
+#if NET46
+            request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
+#endif    
 
             if (httpWebRequest != null)
             {
                 if (options.EnableKeepAlive)
                 {
+#if NET46
                     httpWebRequest.KeepAlive = true;
+#endif    
                 }
             }
 
             request.Method = method;
+#if NET46
             request.Timeout = options.TimeoutMs;
-            
+#endif
+
             if (httpWebRequest != null)
             {
                 if (!string.IsNullOrEmpty(options.Host))
                 {
+#if NET46
                     httpWebRequest.Host = options.Host;
+#elif NETSTANDARD1_6
+                    httpWebRequest.Headers["Host"] = options.Host;
+#endif
                 }
 
                 if (!string.IsNullOrEmpty(options.Referer))
                 {
+#if NET46
                     httpWebRequest.Referer = options.Referer;
+#elif NETSTANDARD1_6
+                    httpWebRequest.Headers["Referer"] = options.Referer;
+#endif
                 }
             }
 
@@ -202,7 +223,10 @@ namespace Emby.Common.Implementations.HttpClientManager
                 if (parts.Length == 2)
                 {
                     request.Credentials = GetCredential(url, parts[0], parts[1]);
+                    // TODO: .net core ??
+#if NET46
                     request.PreAuthenticate = true;
+#endif
                 }
             }
 
@@ -227,11 +251,19 @@ namespace Emby.Common.Implementations.HttpClientManager
                 }
                 else if (string.Equals(header.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
                 {
+#if NET46
                     request.UserAgent = header.Value;
+#elif NETSTANDARD1_6
+                    request.Headers["User-Agent"] = header.Value;
+#endif
                 }
                 else
                 {
+#if NET46
                     request.Headers.Set(header.Key, header.Value);
+#elif NETSTANDARD1_6
+                    request.Headers[header.Key] = header.Value;
+#endif
                 }
             }
         }
@@ -407,8 +439,10 @@ namespace Emby.Common.Implementations.HttpClientManager
 
                 httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
 
+#if NET46
                 httpWebRequest.ContentLength = bytes.Length;
-                httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
+#endif    
+                (await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
             }
 
             if (options.ResourcePool != null)
@@ -885,6 +919,7 @@ namespace Emby.Common.Implementations.HttpClientManager
 
         private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
         {
+#if NET46
             var taskCompletion = new TaskCompletionSource<WebResponse>();
 
             Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
@@ -897,6 +932,9 @@ namespace Emby.Common.Implementations.HttpClientManager
             asyncTask.ContinueWith(callback.OnError, TaskContinuationOptions.OnlyOnFaulted);
 
             return taskCompletion.Task;
+#endif
+
+            return request.GetResponseAsync();
         }
 
         private static void TimeoutCallback(object state, bool timedOut)

+ 12 - 11
Emby.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -6,6 +6,7 @@ using System.Linq;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
+using System.Threading.Tasks;
 using MediaBrowser.Model.Extensions;
 
 namespace Emby.Common.Implementations.Networking
@@ -56,7 +57,7 @@ namespace Emby.Common.Implementations.Networking
 
             if (list.Count == 0)
             {
-				list.AddRange(GetLocalIpAddressesFallback());
+				list.AddRange(GetLocalIpAddressesFallback().Result);
             }
 
 			return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
@@ -170,7 +171,7 @@ namespace Emby.Common.Implementations.Networking
                         var host = uri.DnsSafeHost;
                         Logger.Debug("Resolving host {0}", host);
 
-                        address = GetIpAddresses(host).FirstOrDefault();
+                        address = GetIpAddresses(host).Result.FirstOrDefault();
 
                         if (address != null)
                         {
@@ -193,9 +194,9 @@ namespace Emby.Common.Implementations.Networking
             return false;
         }
 
-        public IEnumerable<IPAddress> GetIpAddresses(string hostName)
+        private Task<IPAddress[]> GetIpAddresses(string hostName)
         {
-            return Dns.GetHostAddresses(hostName);
+            return Dns.GetHostAddressesAsync(hostName);
         }
 
 		private List<IPAddress> GetIPsDefault()
@@ -236,9 +237,9 @@ namespace Emby.Common.Implementations.Networking
 				.ToList();
 		}
 
-		private IEnumerable<IPAddress> GetLocalIpAddressesFallback()
+		private async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback()
         {
-            var host = Dns.GetHostEntry(Dns.GetHostName());
+            var host = await Dns.GetHostEntryAsync(Dns.GetHostName()).ConfigureAwait(false);
 
             // Reverse them because the last one is usually the correct one
             // It's not fool-proof so ultimately the consumer will have to examine them and decide
@@ -279,7 +280,7 @@ namespace Emby.Common.Implementations.Networking
         /// <returns>IPEndPoint.</returns>
         public IPEndPoint Parse(string endpointstring)
         {
-            return Parse(endpointstring, -1);
+            return Parse(endpointstring, -1).Result;
         }
 
         /// <summary>
@@ -290,7 +291,7 @@ namespace Emby.Common.Implementations.Networking
         /// <returns>IPEndPoint.</returns>
         /// <exception cref="System.ArgumentException">Endpoint descriptor may not be empty.</exception>
         /// <exception cref="System.FormatException"></exception>
-        private static IPEndPoint Parse(string endpointstring, int defaultport)
+        private static async Task<IPEndPoint> Parse(string endpointstring, int defaultport)
         {
             if (String.IsNullOrEmpty(endpointstring)
                 || endpointstring.Trim().Length == 0)
@@ -316,7 +317,7 @@ namespace Emby.Common.Implementations.Networking
 
                 //try to use the address as IPv4, otherwise get hostname
                 if (!IPAddress.TryParse(values[0], out ipaddy))
-                    ipaddy = GetIPfromHost(values[0]);
+                    ipaddy = await GetIPfromHost(values[0]).ConfigureAwait(false);
             }
             else if (values.Length > 2) //ipv6
             {
@@ -372,9 +373,9 @@ namespace Emby.Common.Implementations.Networking
         /// <param name="p">The p.</param>
         /// <returns>IPAddress.</returns>
         /// <exception cref="System.ArgumentException"></exception>
-        private static IPAddress GetIPfromHost(string p)
+        private static async Task<IPAddress> GetIPfromHost(string p)
         {
-            var hosts = Dns.GetHostAddresses(p);
+            var hosts = await Dns.GetHostAddressesAsync(p).ConfigureAwait(false);
 
             if (hosts == null || hosts.Length == 0)
                 throw new ArgumentException(String.Format("Host not found: {0}", p));

+ 1 - 1
Emby.Common.Implementations/ScheduledTasks/TaskManager.cs

@@ -249,7 +249,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
             var myTasks = ScheduledTasks.ToList();
 
             var list = tasks.ToList();
-            myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem)));
+            myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem, _systemEvents)));
 
             ScheduledTasks = myTasks.ToArray();
 

+ 16 - 2
Emby.Common.Implementations/project.json

@@ -15,6 +15,7 @@
         "System.Net.Http.WebRequest": "4.0.0.0",
         "System.Net.Primitives": "4.0.0.0",
         "System.Runtime": "4.0.0.0",
+        "System.Runtime.Extensions": "4.0.0.0",
         "System.Text.Encoding": "4.0.0.0",
         "System.Threading": "4.0.0.0",
         "System.Threading.Tasks": "4.0.0.0",
@@ -27,7 +28,9 @@
         },
         "MediaBrowser.Model": {
           "target": "project"
-        }
+        },
+		"SimpleInjector": "3.2.4",
+		"NLog": "4.4.0-betaV15"
       }
     },
     "netstandard1.6": {
@@ -41,7 +44,18 @@
           "target": "project"
         },
         "System.Net.Requests": "4.0.11",
-		"System.Xml.XmlSerializer": "4.0.11"
+		"System.Xml.XmlSerializer": "4.0.11",
+		"System.Net.Http": "4.1.0",
+		"System.Net.Primitives": "4.0.11",
+		"System.Net.Sockets": "4.1.0",
+		"System.Net.NetworkInformation": "4.1.0",
+		"System.Net.NameResolution": "4.0.0",
+		"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
+		"System.Reflection": "4.1.0",
+		"System.Reflection.Primitives": "4.0.1",
+		"System.Runtime.Loader": "4.0.0",
+		"SimpleInjector": "3.2.4",
+		"NLog": "4.4.0-betaV15"
       }
     }
   }

File diff suppressed because it is too large
+ 853 - 6
Emby.Common.Implementations/project.lock.json


Some files were not shown because too many files changed in this diff