title: where in the breeze entity materialization pipeline can i set a non entity object's prototype?
body: <p>this question is basically the same question I asked a few weeks ago... <a href="https://stackoverflow.com/questions/29243183/how-to-tap-into-mappingcontext-processanontype">how to tap into mappingcontext.processAnonType</a>... I marked the question as answered by mistake and since then have not been able to get any follow up. </p>
  
  <p>Basically what I am trying to figure out is a location within the breeze pipeline that i can set a non entity object's prototype when the object is materialized from server results... when breeze processes results from the servers that are not entities, it ends up calling the method below of the helper <code>MappingContext</code> class... this method is as follows:</p>
  
  <pre><code>function processAnonType(mc, node) {
      // node is guaranteed to be an object by this point, i.e. not a scalar          
      var keyFn = mc.metadataStore.namingConvention.serverPropertyNameToClient;
      var result = {};
  
      __objectForEach(node, function (key, value) {
          var newKey = keyFn(key);
          var nodeContext = { nodeType: "anonProp", propertyName: newKey };
          visitNode(value, mc, nodeContext, result, newKey);
      });
      return result;
  }
  </code></pre>
  
  <p>up above the value of "results" is what the client ends up receiving from breeze... this is a perfect place that I could do what it is i want to do just because i have access to the final object ("results") AND the <code>node.$type</code> property... i basically want to parse the <code>node.$type</code> property in order to figure out the prototype of the non entity object... unfortunately it does not appear <code>processAnonType</code> is an interception point within the pipeline... in the previous question i asked, i was directed to look at a custom jsonresultsadapter... i did that but i don't think it will work simply because the jsonresultsadapter does not ever appear to be in the position of changing the value of "results" (the final object returned)... so even if i implement a custom <code>jsonresulsadapter</code> and return new nodes, the value of "results" up above continues to be the same... can anyone please clue me in? thank you</p>
  
  <p>EDIT #1: I already tried using a custom jsonresultsadapter… but this does NOT work for what I am SPECIFICALLY trying to do, UNLESS I am using a very old version of breeze (unlikely) or am missing something really obvious (more likely)... down below I have provided two snippets of breeze code that will hopefully help me explain my conclusion... the first snippet is the “visitandmerge” method of the mappingcontext… towards the bottom of that method you’ll see a call made to “jra.visitnode”… that’s great… it calls my custom jra implementation which returns a “node” property in the result such that the following line will use that node rather than the original one… so far so good… then at the end you’ll see that a call is made to “processmeta” that passes in my custom node… ok fine… but then if you look the “processmeta” code in my case the last “else” block ends up being invoked and a call is made to “processanontype”… this is where the problem is… at this point my custom node is discarded for purposes of creating/instantiating the final object returned to the client… I understand my custom node will be used to create properties for the final object but that's not what I am after... instead I need to manipulate the final object myself by setting its prototype… as I mentioned previously, if you look at the “processanontype” method it creates a new object (var result = {};) and that object is returned to the client, NOT my custom node, which is inline with what the documentation says… please see all the comments I left in the previous post... do you understand what my problem is? I am probably missing something here really obvious… can you please clue me in? thanks again</p>
  
  <pre><code> proto.visitAndMerge = function (nodes, nodeContext) {
      var query = this.query;
      var jra = this.jsonResultsAdapter;
      nodeContext = nodeContext || {};
      var that = this;
      return __map(nodes, function (node) {
          if (query == null &amp;&amp; node.entityAspect) {
              // don't bother merging a result from a save that was not returned from the server.
              if (node.entityAspect.entityState.isDeleted()) {
                  that.entityManager.detachEntity(node);
              } else {
                  node.entityAspect.acceptChanges();
              }
              return node;
          }
  
          var meta = jra.visitNode(node, that, nodeContext) || {};
          node = meta.node || node;
          if (query &amp;&amp; nodeContext.nodeType === "root" &amp;&amp; !meta.entityType) {
              meta.entityType = query._getToEntityType &amp;&amp; query._getToEntityType(that.metadataStore);
          }
          return processMeta(that, node, meta);
      });
  };
  
   function processMeta(mc, node, meta, assignFn) {
      // == is deliberate here instead of ===
      if (meta.ignore || node == null) {
          return null;
      } else if (meta.nodeRefId) {
          var refValue = resolveEntityRef(mc, meta.nodeRefId);
          if (typeof refValue === "function" &amp;&amp; assignFn != null) {
              mc.deferredFns.push(function () {
                  assignFn(refValue);
              });
              return undefined; // deferred and will be set later;
          }
          return refValue;
      } else if (meta.entityType) {
          var entityType = meta.entityType;
          if (mc.mergeOptions.noTracking) {
              node = processNoMerge(mc, entityType, node);
              if (entityType.noTrackingFn) {
                  node = entityType.noTrackingFn(node, entityType);
              } 
              if (meta.nodeId) {
                  mc.refMap[meta.nodeId] = node;
              }
              return node;
          } else {
              if (entityType.isComplexType) {
                  // because we still need to do serverName to client name processing
                  return processNoMerge(mc, entityType, node);
              } else {
                  return mergeEntity(mc, node, meta);
              }
          }
      } else {
          if (typeof node === 'object' &amp;&amp; !__isDate(node)) {
              node = processAnonType(mc, node);
          }
  
          // updating the refMap for entities is handled by updateEntityRef for entities.
          if (meta.nodeId) {
              mc.refMap[meta.nodeId] = node;
          }
          return node;
      }
  }
  </code></pre>