diff --git a/ZeroLevel/Services/Config/Configuration.cs b/ZeroLevel/Services/Config/Configuration.cs
index 385b3b0..efb4e54 100644
--- a/ZeroLevel/Services/Config/Configuration.cs
+++ b/ZeroLevel/Services/Config/Configuration.cs
@@ -2,9 +2,11 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reflection;
using ZeroLevel.Services.Config;
using ZeroLevel.Services.Config.Implementation;
+using ZeroLevel.Services.Reflection;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel
@@ -14,14 +16,13 @@ namespace ZeroLevel
///
/// Application folder path
///
- public static string BaseDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
+ public static readonly string BaseDirectory;
- public static string AppLocation = Assembly.GetEntryAssembly()?.Location;
+ public static readonly string AppLocation;
public const string DEFAULT_SECTION_NAME = "_defaultsection";
#region Ctor
-
static Configuration()
{
_empty = new BaseConfiguration();
@@ -29,6 +30,12 @@ namespace ZeroLevel
_empty.Freeze(true);
_emptySet.FreezeConfiguration(true);
DefaultSet = Configuration.CreateSet();
+ var assembly = EntryAssemblyAttribute.GetEntryAssembly();
+ if (assembly != null)
+ {
+ BaseDirectory = Path.GetDirectoryName(assembly.Location);
+ AppLocation = assembly.Location;
+ }
}
#endregion Ctor
diff --git a/ZeroLevel/Services/Network/BaseSocket.cs b/ZeroLevel/Services/Network/BaseSocket.cs
index de24b00..e1f04b2 100644
--- a/ZeroLevel/Services/Network/BaseSocket.cs
+++ b/ZeroLevel/Services/Network/BaseSocket.cs
@@ -6,7 +6,7 @@ namespace ZeroLevel.Network
{
static BaseSocket()
{
- MAX_FRAME_PAYLOAD_SIZE = Configuration.Default.FirstOrDefault("MAX_FRAME_PAYLOAD_SIZE", DEFAULT_MAX_FRAME_PAYLOAD_SIZE);
+ MAX_FRAME_PAYLOAD_SIZE = Configuration.Default?.FirstOrDefault("MAX_FRAME_PAYLOAD_SIZE", DEFAULT_MAX_FRAME_PAYLOAD_SIZE) ?? DEFAULT_MAX_FRAME_PAYLOAD_SIZE;
}
public static readonly IRouter NullRouter = new NullRouter();
diff --git a/ZeroLevel/Services/Reflection/EntryAssebmlyAttribute.cs b/ZeroLevel/Services/Reflection/EntryAssebmlyAttribute.cs
new file mode 100644
index 0000000..372b4b4
--- /dev/null
+++ b/ZeroLevel/Services/Reflection/EntryAssebmlyAttribute.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace ZeroLevel.Services.Reflection
+{
+ ///
+ /// For certain types of apps, such as web apps,
+ /// returns null. With the , we can designate
+ /// an assembly as the entry assembly by creating an instance of this attribute,
+ /// typically in the AssemblyInfo.cs file.
+ ///
+ /// [assembly: EntryAssembly]
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public sealed class EntryAssemblyAttribute : Attribute
+ {
+ ///
+ /// Lazily find the entry assembly.
+ ///
+ private static readonly Lazy EntryAssemblyLazy = new Lazy(GetEntryAssemblyLazily);
+
+ ///
+ /// Gets the entry assembly.
+ ///
+ /// The entry assembly.
+ public static Assembly GetEntryAssembly()
+ {
+ return EntryAssemblyLazy.Value;
+ }
+
+ ///
+ /// Invoked lazily to find the entry assembly. We want to cache this value as it may
+ /// be expensive to find.
+ ///
+ /// The entry assembly.
+ private static Assembly GetEntryAssemblyLazily()
+ {
+ return Assembly.GetEntryAssembly() ?? FindEntryAssemblyInCurrentAppDomain();
+ }
+
+ ///
+ /// Finds the entry assembly in the current app domain.
+ ///
+ /// The entry assembly.
+ private static Assembly FindEntryAssemblyInCurrentAppDomain()
+ {
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+ var entryAssemblies = new List();
+ foreach (var assembly in assemblies)
+ {
+ // Note the usage of LINQ SingleOrDefault. The EntryAssemblyAttribute's AttrinuteUsage
+ // only allows it to occur once per assembly; declaring it more than once results in
+ // a compiler error.
+ var attribute =
+ assembly.GetCustomAttributes().OfType().SingleOrDefault();
+ if (attribute != null)
+ {
+ entryAssemblies.Add(assembly);
+ }
+ }
+
+ // Note that we use LINQ Single to ensure we found one and only one assembly with the
+ // EntryAssemblyAttribute. The EntryAssemblyAttribute should only be put on one assembly
+ // per application.
+ return entryAssemblies.SingleOrDefault();
+ }
+ }
+}