【问题标题】:where in the breeze entity materialization pipeline can i set a non entity object's prototype?在微风实体物化管道中,我可以在哪里设置非实体对象的原型?
【发布时间】:2015-05-04 18:55:16
【问题描述】:

这个问题与我几周前问的基本相同...how to tap into mappingcontext.processAnonType...我将问题标记为错误回答,此后一直无法得到任何跟进。

基本上我想弄清楚的是在微风管道中的一个位置,当对象从服务器结果中具体化时,我可以设置非实体对象的原型......当微风处理来自非实体服务器的结果时,它最终调用了helperMappingContext类的下面的方法……这个方法如下:

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;
}

高于“结果”的值是客户最终从微风中收到的......这是一个完美的地方,我可以做我想做的事,因为我可以访问最终对象(“结果“)和node.$type属性...我基本上想解析node.$type属性以找出非实体对象的原型...不幸的是它没有出现processAnonType是一个拦截点管道...在我问的上一个问题中,我被指示查看自定义 jsonresultsadapter...我这样做了,但我认为它不会工作,因为 jsonresultsadapter 似乎从来没有处于更改“结果”的值(返回的最终对象)......所以即使我实现了自定义 jsonresulsadapter 并返回新节点,上面的“结果”的值仍然是相同的......任何人都可以请提示我?谢谢

编辑#1:我已经尝试过使用自定义 jsonresultsadapter ......但这不适用于我特别想要做的事情,除非我使用的是非常旧版本的微风(不太可能)或遗漏了一些非常明显的东西(更多可能)...在下面我提供了两个sn-ps的微风代码,希望能帮助我解释我的结论...第一个sn-p是mappingcontext的“visitandmerge”方法...在那个方法的底部你'将看到对“jra.visitnode”的调用......这很好......它调用了我的自定义 jra 实现,它在结果中返回一个“node”属性,这样下一行将使用该节点而不是原始节点......到目前为止好……那么最后你会看到对传入我的自定义节点的“processmeta”进行了调用……好吧……但是如果你在我的例子中查看“processmeta”代码,最后一个“else”块结束了被调用并调用“processanontype”......这就是问题所在......此时我的自定义节点被丢弃 f或创建/实例化返回给客户端的最终对象的目的……我知道我的自定义节点将用于为最终对象创建属性,但这不是我所追求的……相反,我需要自己操作最终对象通过设置它的原型……正如我之前提到的,如果您查看“processanontype”方法,它会创建一个新对象(var result = {};)并且该对象返回给客户端,而不是我的自定义节点,它与文档说……请查看我在上一篇文章中留下的所有 cmets……你明白我的问题是什么吗?我可能在这里遗漏了一些非常明显的东西……你能告诉我吗?再次感谢

 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 && 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 && nodeContext.nodeType === "root" && !meta.entityType) {
            meta.entityType = query._getToEntityType && 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" && 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' && !__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;
    }
}

【问题讨论】:

    标签: breeze


    【解决方案1】:

    您应该不需要修改 processAnonType 方法。

    jsonResultsAdapter 中的visitNode 方法的参数包含您说需要的有关正在访问的节点的所有信息。 (请参阅本文底部的链接)。 visitNode 的结果是一个具有以下属性的对象:

    entityType:您应该为匿名类型返回 null

    nodeIdnodeRefId:(匿名对象可能不需要,除非您计划将多个 refs 返回到同一个对象)

    ignore:布尔值 -(如果您想完全忽略该节点)。

    node:您可以在此处获取传入节点(visitNode 参数列表中的第一个参数)并对其进行修改,或者返回一个代表您的 anonType 实例的全新节点对象。该对象将原封不动地返回给客户端,因此您可以使用所需的任何原型创建对象的新实例。如果您不设置此属性,则将使用原始传入节点。

    passThru:(在微风版本 > v 1.5.4 中可用)布尔​​值 - 您应该返回 true 以完整地返回节点(以上),无需任何进一步处理。

    所以你的 visitNode 看起来像这样:

    visitNode: function(node, mappingContext, nodeContext) {
        // 'isAnonType' is your method that determines if this is an anon type
        var isAnon = isAnonType(node.$type);
        if (isAnonType) {
          // 'createCustomAnonNode' is your method where you create a copy of the node with whatever prototype you want.
          // prototype you want. 
          var newNode = createCustomAnonNode(node); 
          return {
             return { passThru: true, node: newNode };   
          }
        } else {
          // assuming that you kept track of the default JsonResultsAdapter;
          return defaultAdapter.visitNode(node, mappingContext, nodeContext); 
    
        }
     }
    

    更多详情,请参见:

    http://www.getbreezenow.com/documentation/jsonresultsadapters

    【讨论】:

    • 谢谢 jay...请查看我上面的编辑#1...cmets 太短,无法在此处放置该信息...再次感谢
    • 没关系...我认为您的意思是在自定义节点中我应该以某种方式返回 $type 属性,以便客户端可以处理它...而我直接在管道...我明白了...谢谢
    • 其实我觉得周杰伦说的有些不一样。 “AnonType”只是我们说“不是EntityType 的类型”的方式。仔细检查传入节点并决定它是否值得特殊处理是你的工作;这就是您的isAnonType 方法的重点(您可能想要检查整个node 而不仅仅是node.$type)。如果您确定该节点是“匿名的”(在 Breeze 意义上),您可以对该节点执行任何您想要的操作,并确信 Breeze 会将其传递给调用者如您所修改的 i>.
    • @giancarloa:你说得对,我错过了我们实际上通过迭代它们的属性和处理内部来处理 anonTypes 的事实。因此,我刚刚为 visitNode 返回类型添加了一个新属性,称为“passThru”,如果您将此属性设置为 true(并且不设置“entityType”,那么微风将不会尝试对您返回的进行任何进一步处理匿名节点。这将在本周晚些时候在 v 1.5.4 中发布,或者您可以直接从 GitHub 获取最新版本。
    • 我们刚刚更新了 JRA 文档以反映此处的讨论以及新的 passThru 标志......它将出现在下一个版本中。感谢您的反馈和启发。
    猜你喜欢
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 2014-11-02
    • 2013-04-05
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多