- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有这个数据结构声明:
[ProtoContract]
public class NotACollectionHolder
{
public NotACollection some_objects;
}
[ProtoContract(IgnoreListHandling = true, ImplicitFields = ImplicitFields.AllPublic)]
public class NotACollection : IEnumerable<int>
{
public int some_data;
// something looks like a collection API
public void Add(int a) { }
public IEnumerator<int> GetEnumerator() { throw new NotImplementedException(); }
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}
我正在通过以下代码手动将字段注册到 MetaType
:
MetaType meta = RuntimeTypeModel.Default.Add(typeof(NotACollectionHolder), false);
ValueMember member = meta.AddField(1, "some_objects", itemType: null, defaultType: null);
string proto = Serializer.GetProto<NotACollectionHolder>();
我将 NotACollection
标记为 IgnoreListHandling
。我试图通过提供 itemType: null, defaultType: null
来强制 AddField
忽略 NotACollection
看起来像集合的事实。
不过,我的 member.ItemType
不为空,member.DefaultType
也不为空。并且 some_objects
成为生成的 proto
中的一个 repeated
字段:
message NotACollectionHolder {
repeated int32 some_objects = 1;
}
我希望 proto
看起来像这样:
message NotACollection {
optional int32 some_data = 1 [default = 0];
}
message NotACollectionHolder {
optional NotACollection some_objects = 1;
}
我怎样才能做到这一点?我究竟做错了什么?我如何强制 protobuf-net 将此字段视为非集合字段?
提前致谢。
最佳答案
我认为这可能是 RuntimeTypeModel
的错误或限制应用程序接口(interface)。
确定是否为 ValueMember
的方法是一个集合是RuntimeTypeModel.ResolveListTypes()
.当传入的 itemType
为 null 时,它会尝试推断集合项类型。仅使用静态属性为 NotACollectionHolder
构建合约时,例如:
var model = TypeModel.Create();
var schema = model.GetSchema(typeof(NotACollectionHolder));
然后 ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour(bool isEnum, ProtoMemberAttribute normalizedAttribute)
调用以创建初始化 ValueMember
。它具有以下逻辑:
// check for list types
ResolveListTypes(model, effectiveType, ref itemType, ref defaultType);
// but take it back if it is explicitly excluded
if(itemType != null)
{ // looks like a list, but double check for IgnoreListHandling
int idx = model.FindOrAddAuto(effectiveType, false, true, false);
if(idx >= 0 && model[effectiveType].IgnoreListHandling)
{
itemType = null;
defaultType = null;
}
}
注意到对 IgnoreListHandling
的显式检查了吗?这正确地阻止了 some_objects
被序列化为一个集合。
相反,如果以编程方式添加 ValueMember
,如下所示:
var model = TypeModel.Create();
var meta = model.Add(typeof(NotACollectionHolder), false);
var member = meta.AddField(1, "some_objects", null, null);
var schema = model.GetSchema(typeof(NotACollectionHolder));
然后 MetaType.AddField(int fieldNumber, string memberName, Type itemType, Type defaultType, object defaultValue)
被称为,它只是做:
ResolveListTypes(model, miType, ref itemType, ref defaultType);
请注意没有检查IgnoreListHandling
?这是你的问题的原因。
不幸的是,ValueType.itemType
是只读的并且 MetaType[int fieldNumber]
是只获取的,所以似乎没有一个简单的 API 可以调用来解决这个问题。你可以考虑 reporting an issue .
我能找到的唯一解决方法是为 NotACollectionHolder
类型引入一个代理项,如下所示:
[ProtoContract]
internal class NotACollectionHolderSurrogate
{
[ProtoMember(1)]
internal NotACollectionSurrogate some_objects;
public static implicit operator NotACollectionHolder(NotACollectionHolderSurrogate input)
{
if (input == null)
return null;
return new NotACollectionHolder { some_objects = input.some_objects };
}
public static implicit operator NotACollectionHolderSurrogate(NotACollectionHolder input)
{
if (input == null)
return null;
return new NotACollectionHolderSurrogate { some_objects = input.some_objects };
}
}
[ProtoContract]
internal class NotACollectionSurrogate
{
[ProtoMember(1)]
public int some_data;
public static implicit operator NotACollection(NotACollectionSurrogate input)
{
if (input == null)
return null;
return new NotACollection { some_data = input.some_data };
}
public static implicit operator NotACollectionSurrogate(NotACollection input)
{
if (input == null)
return null;
return new NotACollectionSurrogate { some_data = input.some_data };
}
}
然后做:
var model = TypeModel.Create();
model.Add(typeof(NotACollectionHolder), false).SetSurrogate(typeof(NotACollectionHolderSurrogate));
var schema = model.GetSchema(typeof(NotACollectionHolder));
生成的合约是按要求的:
message NotACollectionHolderSurrogate {
optional NotACollectionSurrogate some_objects = 1;
}
message NotACollectionSurrogate {
optional int32 some_data = 1 [default = 0];
}
关于c# - protobuf-net AddField 忽略 IgnoreListHandling,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42600663/
我想在查找结果中添加额外的字段,但我需要一个条件。每个用户都有一个关系状态(本地字段),应该将其添加到每个用户的查找结果中,但它会将每个“状态”添加到每个用户。 db.getCollection('r
我试图仅在满足特定条件时才添加字段,例如,如果数组大小 > 0 则使用 $addFields 添加字段“date”,否则不添加 当使用 $cond 时,它是一个 bool 值,所以我必须添加一个带有日
我目前正在尝试制作一个会倒计时到特定日期的 discord 机器人。现在我将参数传递到 .json 文件的文件夹中,其中仅存储事件名称和发布日期/事件日期。 bot.on('ready', () =>
设置自定义表单。 Magento 不使用 addField 的“value”属性。建议? 代码: $form = new Varien_Data_Form(array( 'id' => 'ed
使用 migrations ,我需要向模型添加一个新字段(外键)。我知道可以通过以下方式完成: migrations.AddField( model_name='MyModel
我是新的 Mongodb 开发人员,我写了 mongodb 聚合。我的领域 lampStatus 之一:“OFF”是 30 条记录,我正在使用“{ $match: {lampStatus : “OFF
我正在努力解决一个恼人的问题。我在查询中使用聚合,我需要加入一些集合,并且输出必须是一个对象。这是我的代码... usersModel.aggregate([ { $match
我是新的 Mongodb 开发人员,我写了 mongodb 聚合。我的领域 lampStatus 之一:“OFF”是 30 条记录,我正在使用“{ $match: {lampStatus : “OFF
我正在努力解决一个恼人的问题。我在查询中使用聚合,我需要加入一些集合,并且输出必须是一个对象。这是我的代码... usersModel.aggregate([ { $match
我将云中提供的视频的视频 ID 存储在我的 mongodb 集合中。当我的前端对该视频进行 API 调用时,我想根据该视频 ID 返回格式化的 URL。我有一个函数可以执行此操作,但我无法让它与 $a
我知道可以 .spliceFields() ,只要我指明要删除的索引和字段数即可。但是由于我有很多嵌入并且我希望它们拼接一个主嵌入中的每个字段,我想创建一个变量,其值等于主嵌入中的字段数,因为我可能会
我想弄清楚如何使用 $addFields我用来更新文档的函数中的操作。生成这个字段的逻辑很简单,我只是拉出数组中的最后一个对象,如下所示: { $addFields: { activeWo
对于 Magento 后端,我创建了一个 Varien_Form 来显示。 class MyNamespace_MyModule_Block_Adminhtml_MyModule_Edit_Tabs_
这个问题在这里已经有了答案: Retrieving specific fields using the Elasticsearch Java API (1 个回答) 关闭 7 年前。 这是这个问题的
我有一个 solrobject,我想添加一个字段。 当我尝试添加字段时它抛出 PHP Fatal error: Call to undefined method SolrObject::addF
我有以下结构: { "_id":"some_id", "tweets":[ { "id":"1077633161922785281",
我有这个数据结构声明: [ProtoContract] public class NotACollectionHolder { public NotACollection some_objec
我有以下查询。 db.Collection.aggregate([ { "$match":{ "index": 1
在我的 mongodb 查询中,我使用 $addFields 添加 ID 字段,该字段连接了其他三个字段。我的问题是,如果我将新添加的字段与我要查询的值匹配,我将得不到任何结果。对于其他领域,它们工作
MongoDb 版本 3.4.4 如何为数组快照中的每个对象聚合一个新键“total”,其值是“course”和“quantity”的乘积。 示例文档: { cur: "EUR", s
我是一名优秀的程序员,十分优秀!