在breeze实体物化管道的何处可以设置非实体对象';什么是原型?
这个问题基本上和我几周前问的问题一样。。。我把这个问题标为答错了,从那以后就没能得到任何跟进 基本上,我试图找出的是breeze管道中的一个位置,当对象从服务器结果物化时,我可以设置一个非实体对象的原型。。。当breeze处理来自非实体服务器的结果时,它最终调用helper在breeze实体物化管道的何处可以设置非实体对象';什么是原型?,breeze,Breeze,这个问题基本上和我几周前问的问题一样。。。我把这个问题标为答错了,从那以后就没能得到任何跟进 基本上,我试图找出的是breeze管道中的一个位置,当对象从服务器结果物化时,我可以设置一个非实体对象的原型。。。当breeze处理来自非实体服务器的结果时,它最终调用helperMappingContextclass的下面的方法。。。该方法如下: function processAnonType(mc, node) { // node is guaranteed to be an object
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 nodeId和nodeRefId:(可能不需要匿名对象,除非您计划将多个引用返回到同一对象) 忽略:布尔值-(如果要完全忽略节点) 节点:在这里,您可以获取传入节点(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(并且不设置