/// <summary> /// Loads the Resource from the specified <see cref="Stream"/>. You shouldn't need this method in almost all cases. /// Only use it when you know exactly what you're doing. Consider requesting the Resource from the <see cref="ContentProvider"/> instead. /// </summary> /// <typeparam name="T"> /// Desired Type of the returned reference. Does not affect the loaded Resource in any way - it is simply returned as T. /// Results in returning null if the loaded Resource's Type isn't assignable to T. /// </typeparam> /// <param name="str">The stream to load the Resource from.</param> /// <param name="resPath">The path that is assumed as the loaded Resource's origin.</param> /// <param name="loadCallback">An optional callback that is invoked right after loading the Resource, but before initializing it.</param> /// <param name="initResource"> /// Specifies whether or not the Resource is initialized by calling <see cref="Resource.OnLoaded"/>. Never attempt to use /// uninitialized Resources or register them in the <see cref="ContentProvider"/>. /// </param> /// <returns>The Resource that has been loaded.</returns> public static T Load <T>(Serializer formatter, string resPath = null, Action <T> loadCallback = null, bool initResource = true) where T : Resource { T newContent = null; try { Resource res = formatter.ReadObject <Resource>(); if (res == null) { throw new Exception("Deserializing Resource failed."); } res.initState = InitState.Initializing; res.path = resPath; if (loadCallback != null) { loadCallback(res as T); // Callback before initializing. } if (initResource) { Init(res); } newContent = res as T; } catch (Exception e) { Logs.Core.WriteError("Can't load {0} from '{1}', because an error occurred: {3}{2}", LogFormat.Type(typeof(T)), resPath ?? formatter.ToString(), LogFormat.Exception(e), Environment.NewLine); } return(newContent); }
/// <summary> /// Returns a string that can be used for representing a <see cref="System.Reflection.TypeInfo"/> in log entries. /// </summary> /// <param name="type"></param> /// <returns></returns> public static string Type(TypeInfo type) { if (type == null) { return("null"); } return(LogFormat.Type(type.AsType())); }
public override string ToString() { if (this.SkipIfExists > 0) { return(string.Format("Skip {0} if {1} exists", this.SkipIfExists, LogFormat.Type(this.RequiredType))); } else { return(string.Format("Require {0} or create {1}", LogFormat.Type(this.RequiredType), LogFormat.Type(this.CreateType))); } }
/// <summary> /// Adds an already loaded plugin Assembly to the internal Cohee T registry. /// You shouldn't need to call this method in general, since Cohee manages its plugins /// automatically. /// </summary> /// <remarks> /// This method can be useful in certain cases when it is necessary to treat an Assembly as a /// Cohee plugin, even though it isn't located in the Plugins folder, or is not available /// as a file at all. A typical case for this is Unit Testing where the testing Assembly may /// specify additional Duality types such as Components, Resources, etc. /// </remarks> /// <param name="pluginAssembly"></param> /// <param name="pluginFilePath"></param> /// <returns></returns> public T LoadPlugin(Assembly pluginAssembly, string pluginFilePath) { this.disposedPlugins.Remove(pluginAssembly); string asmName = pluginAssembly.GetShortAssemblyName(); T plugin = this.pluginRegistry.Values.FirstOrDefault(p => p.AssemblyName == asmName); if (plugin != null) { return(plugin); } try { TypeInfo pluginType = pluginAssembly.ExportedTypes .Select(t => t.GetTypeInfo()) .FirstOrDefault(t => typeof(T).GetTypeInfo().IsAssignableFrom(t)); if (pluginType == null) { throw new Exception(string.Format( "Plugin does not contain a public {0} class.", typeof(T).Name)); } plugin = (T)pluginType.CreateInstanceOf(); if (plugin == null) { throw new Exception(string.Format( "Failed to instantiate {0} class.", LogFormat.Type(pluginType.GetType()))); } plugin.FilePath = pluginFilePath; plugin.FileHash = this.assemblyLoader.GetAssemblyHash(pluginFilePath); this.pluginRegistry.Add(plugin.AssemblyName, plugin); } catch (Exception e) { this.pluginLog.WriteError("Error loading plugin: {0}", LogFormat.Exception(e)); this.disposedPlugins.Add(pluginAssembly); plugin = null; } return(plugin); }
/// <summary> /// Returns a string that can be used for representing an exception in log entries. /// It usually does not include the full call stack and is significantly shorter than /// an <see cref="System.Exception">Exceptions</see> ToString method. /// </summary> /// <param name="e"></param> /// <returns></returns> public static string Exception(Exception e, bool callStack = true) { if (e == null) { return("null"); } string eName = LogFormat.Type(e.GetType()); return(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}: {1}{3}CallStack:{3}{2}", eName, e.Message, e.StackTrace, Environment.NewLine)); }
public void EnsureCreationChain(ComponentRequirementMap map) { if (this.initCreationChain == RecursiveInit.Initialized) { return; } if (this.initCreationChain == RecursiveInit.InProgress) { Logs.Core.WriteWarning( "Detected a cyclic Component requirement in {0}. Requirements can not be ensured for cyclic dependencies.", LogFormat.Type(this.Component)); return; } this.initCreationChain = RecursiveInit.InProgress; this.InitCreationChain(map); this.initCreationChain = RecursiveInit.Initialized; }
/// <summary> /// Clears the specified constraint graph of all loops. /// </summary> /// <param name="graph"></param> private static void ResolveConstraintLoops(Dictionary <Type, List <OrderConstraint> > graph) { while (true) { List <OrderConstraint> loop = FindConstraintLoop(graph); if (loop == null) { return; } // Found a loop? Find the weakest link in it OrderConstraint weakestLink = loop[0]; for (int i = 1; i < loop.Count; i++) { OrderConstraint link = loop[i]; if ((int)link.Priority < (int)weakestLink.Priority) { weakestLink = link; } } // If the loops weakest link was an explicit constraint, log a warning if ((int)weakestLink.Priority >= (int)ConstraintPriority.ExplicitWeak) { Logs.Core.WriteWarning( "Found a loop in the component execution order constraint graph. Ignoring the weakest constraint " + "({0} must be executed before {1}). Please check your ExecutionOrder attributes.", LogFormat.Type(weakestLink.FirstType), LogFormat.Type(weakestLink.LastType)); } // Remove the weakest link List <OrderConstraint> links = graph[weakestLink.FirstType]; links.Remove(weakestLink); if (links.Count == 0) { graph.Remove(weakestLink.FirstType); } } }
private static CreateMethod CreateObjectActivator(TypeInfo typeInfo, out object firstResult) { Exception lastError = null; CreateMethod activator; firstResult = null; // Filter out non-instantiatable Types if (typeInfo.IsAbstract || typeInfo.IsInterface || typeInfo.IsGenericTypeDefinition) { activator = nullObjectActivator; } // If the caller wants a string, just return an empty one else if (typeInfo.AsType() == typeof(string)) { activator = () => ""; } // If the caller wants an array, create an empty one else if (typeInfo.IsArray && typeInfo.GetArrayRank() == 1) { activator = () => Array.CreateInstance(typeInfo.GetElementType(), 0); } // For structs, boxing a default(T) is sufficient else if (typeInfo.IsValueType) { var lambda = Expression.Lambda<CreateMethod>(Expression.Convert(Expression.Default(typeInfo.AsType()), typeof(object))); activator = lambda.Compile(); } else { activator = nullObjectActivator; // Retrieve constructors, sorted from trivial to parameter-rich ConstructorInfo[] constructors = typeInfo.DeclaredConstructors .Where(c => !c.IsStatic) .Select(c => new { Info = c, ParamCount = c.GetParameters().Length }) .OrderBy(s => s.ParamCount) .Select(s => s.Info) .ToArray(); foreach (ConstructorInfo con in constructors) { // Prepare constructor argument values - just use default(T) for all of them. ParameterInfo[] conParams = con.GetParameters(); Expression[] args = new Expression[conParams.Length]; for (int i = 0; i < args.Length; i++) { Type paramType = conParams[i].ParameterType; args[i] = Expression.Default(paramType); } // Compile a lambda method invoking the constructor var lambda = Expression.Lambda<CreateMethod>(Expression.New(con, args)); activator = lambda.Compile(); // Does it work? firstResult = CheckActivator(activator, out lastError); if (firstResult != null) break; } // If there were no suitable constructors, log a generic warning. if (constructors.Length == 0) { Logs.Core.WriteWarning( "Failed to create object of Type {0}. Make sure there is a trivial constructor.", LogFormat.Type(typeInfo)); } } // Test whether our activation method really works, replace with dummy if not if (firstResult == null) { // If we didn't yet try to create an object instance or value, do it now. if (lastError == null) { firstResult = CheckActivator(activator, out lastError); } // If there was an error / Exception thrown while creating the object, inform someone. if (lastError != null) { // If it's a problem in a static constructor, get the inner exception to know what's actually wrong. if (lastError is TypeInitializationException) { Logs.Core.WriteError("Failed to initialize Type {0}: {1}", LogFormat.Type(typeInfo), LogFormat.Exception(lastError.InnerException)); } // Otherwise, just do a regular error log. else { Logs.Core.WriteError("Failed to create object of Type {0}: {1}", LogFormat.Type(typeInfo), LogFormat.Exception(lastError)); } } } // If we still don't have anything, just use a dummy. if (firstResult == null) activator = nullObjectActivator; return activator; }
internal static void InitBackend <T>(out T target, Func <Type, IEnumerable <TypeInfo> > typeFinder = null) where T : class, ICoheeBackend { if (typeFinder == null) { typeFinder = GetAvailCoheeTypes; } Logs.Core.Write("Initializing {0}...", LogFormat.Type(typeof(T))); Logs.Core.PushIndent(); // Generate a list of available backends for evaluation List <ICoheeBackend> backends = new List <ICoheeBackend>(); foreach (TypeInfo backendType in typeFinder(typeof(ICoheeBackend))) { if (backendType.IsInterface) { continue; } if (backendType.IsAbstract) { continue; } if (!backendType.IsClass) { continue; } if (!typeof(T).GetTypeInfo().IsAssignableFrom(backendType)) { continue; } ICoheeBackend backend = backendType.CreateInstanceOf() as ICoheeBackend; if (backend == null) { Logs.Core.WriteWarning("Unable to create an instance of {0}. Skipping it.", backendType.FullName); continue; } backends.Add(backend); } // Sort backends from best to worst backends.StableSort((a, b) => b.Priority > a.Priority ? 1 : -1); // Try to initialize each one and select the first that works T selectedBackend = null; foreach (T backend in backends) { if (appData != null && appData.SkipBackends != null && appData.SkipBackends.Any(s => string.Equals(s, backend.Id, StringComparison.OrdinalIgnoreCase))) { Logs.Core.Write("Backend '{0}' skipped because of AppData settings.", backend.Name); continue; } bool available = false; try { available = backend.CheckAvailable(); if (!available) { Logs.Core.Write("Backend '{0}' reports to be unavailable. Skipping it.", backend.Name); } } catch (Exception e) { available = false; Logs.Core.WriteWarning("Backend '{0}' failed the availability check with an exception: {1}", backend.Name, LogFormat.Exception(e)); } if (!available) { continue; } Logs.Core.Write("{0}...", backend.Name); Logs.Core.PushIndent(); { try { backend.Init(); selectedBackend = backend; } catch (Exception e) { Logs.Core.WriteError("Failed: {0}", LogFormat.Exception(e)); } } Logs.Core.PopIndent(); if (selectedBackend != null) { break; } } // If we found a proper backend and initialized it, add it to the list of active backends if (selectedBackend != null) { target = selectedBackend; TypeInfo selectedBackendType = selectedBackend.GetType().GetTypeInfo(); corePluginManager.LockPlugin(selectedBackendType.Assembly); } else { target = null; } Logs.Core.PopIndent(); }
/// <summary> /// Returns an existing <see cref="ProfileCounter"/> with the specified name. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="name">The <see cref="ProfileCounter"/> name to use for this measurement. For nested measurements, use path strings, e.g. "ParentCounter\ChildCounter"</param> /// <returns></returns> public static T GetCounter <T>(string name) where T : ProfileCounter { if (name == null) { return(null); } ProfileCounter c; if (!counterMap.TryGetValue(name, out c)) { return(null); } T cc = c as T; if (cc == null) { throw new InvalidOperationException(string.Format("The specified performance counter '{0}' is not a {1}.", name, LogFormat.Type(typeof(T)))); } return(cc); }