/// <summary> /// Loads the Object identified by the given Node as an object of the given type based on information from the Configuration Graph /// </summary> /// <param name="g">Configuration Graph</param> /// <param name="objNode">Object Node</param> /// <param name="targetType">Target Type</param> /// <returns></returns> /// <remarks> /// <para> /// Callers of this method should be careful to check that the Object returned is of a usable type to them. The Target Type parameter does not guarantee that the return value is of that type it is only used to determine which registered instances of <see cref="IObjectLoader">IObjectLoader</see> are potentially capable of creating the desired Object /// </para> /// <para> /// Callers should also take care that any Objects returned from this method are disposed of when the caller no longer has a use for them as otherwise the reference kept in the cache here will cause the Object to remain in-memory consuming resources /// </para> /// </remarks> public static Object LoadObject(IGraph g, INode objNode, Type targetType) { if (targetType == null) throw new DotNetRdfConfigurationException("Unable to load the Object identified by the Node '" + objNode.ToString() + "' as a null target type was provided - this may be due to a failure to specify a fully qualified type name with the dnr:type property for this object"); if (objNode == null) throw new DotNetRdfConfigurationException("Unable to load an Object as a null Object Node was provided"); if (objNode.NodeType == NodeType.GraphLiteral || objNode.NodeType == NodeType.Literal) { throw new DotNetRdfConfigurationException("Unable to load an Object as the Object Node was not a URI/Blank Node as required"); } //Use an Object caching mechanism to avoid instantiating the same thing multiple times since this could be VERY costly CachedObjectKey key = new CachedObjectKey(objNode, g); if (_cache.ContainsKey(key)) { if (_cache[key] == null) { //This means we've begun trying to cache the Object but haven't loaded it yet //i.e. we've encountered an indirect circular reference or the caller failed to check //for direct circular references with the CheckCircularReference() method throw new DotNetRdfConfigurationException("Unable to load the Object identified by the Node '" + objNode.ToString() + "' as we have already started trying to load this Object which indicates that your Configuration Graph contains a circular reference"); } else if (_cache[key] is UnloadableObject) { //We don't retry loading if we fail throw new DotNetRdfConfigurationException("Unable to load the Object identified by the Node '" + objNode.ToString() + "' as previous attempt(s) to load the Object failed. Call ClearCache() before attempting loading if you wish to retry loading"); } else { //Return from Cache return _cache[key]; } } else { _cache.Add(key, null); } Object temp = null; //Try and find an Object Loader that can load this object try { foreach (IObjectFactory loader in _factories) { if (loader.CanLoadObject(targetType)) { if (loader.TryLoadObject(g, objNode, targetType, out temp)) break; } } } catch (DotNetRdfConfigurationException) { _cache[key] = new UnloadableObject(); throw; } catch (Exception ex) { _cache[key] = new UnloadableObject(); throw new DotNetRdfConfigurationException("Unable to load the Object identified by the Node '" + objNode.ToString() + "' as an error occurred in the Object Loader which attempted to load it", ex); } //Error or return if (temp == null) throw new DotNetRdfConfigurationException("Unable to load the Object identified by the Node '" + objNode.ToString() + "' as an instance of type '" + targetType.ToString() + "' since no Object Loaders are able to load this type"); _cache[key] = temp; return temp; }
/// <summary> /// Gets whether the given Object has already been loaded and cached /// </summary> /// <param name="g">Configuration Graph</param> /// <param name="objNode">Object Node</param> /// <returns></returns> /// <remarks> /// If this returns true then loading that object again should be essentially instantaneous as it will come from the cache /// </remarks> public static bool IsCached(IGraph g, INode objNode) { CachedObjectKey key = new CachedObjectKey(objNode, g); return _cache.ContainsKey(key); }