在breeze实体物化管道的何处可以设置非实体对象';什么是原型?

在breeze实体物化管道的何处可以设置非实体对象';什么是原型?,breeze,Breeze,这个问题基本上和我几周前问的问题一样。。。我把这个问题标为答错了,从那以后就没能得到任何跟进 基本上,我试图找出的是breeze管道中的一个位置,当对象从服务器结果物化时,我可以设置一个非实体对象的原型。。。当breeze处理来自非实体服务器的结果时,它最终调用helperMappingContextclass的下面的方法。。。该方法如下: function processAnonType(mc, node) { // node is guaranteed to be an object

这个问题基本上和我几周前问的问题一样。。。我把这个问题标为答错了,从那以后就没能得到任何跟进

基本上,我试图找出的是breeze管道中的一个位置,当对象从服务器结果物化时,我可以设置一个非实体对象的原型。。。当breeze处理来自非实体服务器的结果时,它最终调用helper
MappingContext
class的下面的方法。。。该方法如下:

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;
}
高于“结果”值的是客户最终从breeze收到的结果。。。这是一个完美的地方,我可以做我想做的事情,因为我可以访问最终对象(“结果”)和
节点。$type
属性。。。我基本上想要解析
节点。$type
属性,以便找出非实体对象的原型。。。不幸的是,
processAnonType
似乎不是管道中的拦截点。。。在我问的前一个问题中,我被要求查看一个定制的jsonresultsadapter。。。我这样做了,但我认为它不会简单地工作,因为JSONResultAdapter似乎从未处于更改“results”(最终返回的对象)值的位置。。。因此,即使我实现一个定制的
jsonresultsadapter
并返回新节点,上面的“results”值仍然是相同的。。。有人能给我提供线索吗?多谢各位

编辑#1:我已经尝试过使用自定义JSONResultAdapter…但这不适用于我特别尝试的操作,除非我使用的是非常旧的breeze版本(不太可能)或缺少一些非常明显的东西(更有可能)。。。下面我提供了两段breeze代码,希望能帮助我解释我的结论。。。第一个片段是mappingcontext的“visitandmerge”方法…在该方法的底部,您将看到对“jra.visitnode”的调用…太棒了…它调用了我的自定义jra实现,返回一个“节点”属性,这样下面的一行将使用该节点而不是原始节点…到目前为止还不错…然后在最后,您将看到对传入自定义节点的“processmeta”进行了调用…好吧,很好…但是如果您查看我的示例中的“processmeta”代码,最后一个“else”块最终被调用并调用“processanontype”…这就是问题所在…此时,为了创建/实例化返回给客户端的最终对象,我的自定义节点被丢弃…我知道我的自定义节点将用于为最终对象创建属性,但这不是我想要的。。。相反,我需要自己通过设置其原型来操作最终对象…正如我前面提到的,如果您查看“processanontype”方法,它将创建一个新对象(var result={};),并且该对象将返回给客户机,而不是我的自定义节点,这与文档中的内容一致…请查看我在上一篇文章中留下的所有评论。。。你明白我的问题是什么吗?我可能错过了一些非常明显的东西…你能给我一些线索吗?再次感谢

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

您不需要修改processAnonType方法

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

entityType:匿名类型应返回null

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

忽略:布尔值-(如果要完全忽略节点)

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

passThru:(在breeze versions>v1.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); 

    }
 }
有关详细信息,请参见:


谢谢你,杰。。。请参阅我的编辑#1以上。。。评论太短,无法将该信息放在此处。。。再次谢谢你,请记住。。。我想你说的是,在自定义节点中,我应该以某种方式返回$type属性,以便客户端可以处理它。。。而我正在寻找一些直接在管道中的东西。。。我明白了。。。谢谢,实际上,我觉得杰伊说的有些不同。“AnonType”只是我们说“不是
实体类型的类型”。您的工作是仔细检查传入节点,并决定它是否值得特殊处理;这就是您的
isAnonType
方法的要点(您可能希望检查整个
节点,而不仅仅是
节点。$type
)。如果您确定该节点是“匿名的”(在Breeze的意义上),您可以对该节点执行任何操作,并确信Breeze会按照您的修改将其传递给调用者。@giancarloa:您是对的,我忽略了一个事实,即我们实际上是通过迭代其属性和处理内部结构来处理anonTypes的。因此,我刚刚在visitNode返回类型中添加了一个名为“passThru”的新属性,如果您将该属性设置为true(并且不设置