- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我目前正在尝试与首先使用 C# 的 BinaryFormatter 格式化后通过网络发送数据的程序进行互操作。这是一个愚蠢的想法,我讨厌它,但我必须与之互操作。
我知道字体是什么样的,我知道它的确切布局。但由于各种原因,我无法在我的程序中添加对该特定程序集的引用。
考虑到 BinaryFormatter 与特定类型/版本的紧密耦合,尽管知道数据结构,但我似乎无法找到一种方法来反序列化它。
我目前正在考虑创建一个具有所有正确属性的假程序集并尝试将其链接(看起来真的很乱),或者手动尝试遍历二进制流并提取我正在寻找的值(我正在查看关于此的 MS 文档,关于布局一目了然)。
还有其他好点子吗,或者过去有没有人在这方面取得过成功?似乎我知道我需要的所有信息,而 BinaryFormatter 只是出了名的脆弱。
编辑:
要回答下面的问题(顺便说一句,这是一个很好的观点)有几个原因。
项目清洁度。为一个功能添加一个 5MB 的外部 .exe 引用有点不对。
与我交互操作的设备在世界各地部署了各种版本。我关心的项目的内部数据结构在所有项目中都是相同的,但程序集的版本不同,导致 BinaryFormatter 损坏。我可以将二进制流转换为字符串,搜索版本号,然后加载正确的版本,但现在我有十几个 .exe 等待我加载正确的版本。然后该方案不是很适合 future (好吧,整个方案并不是真正的 future 证明,但我至少想抽象出 BinaryFormatter 的一些脆弱性以使我的工作更轻松)。仅仅写下这个回复就让我开始考虑使用 emit 或类似的东西来动态创建自定义程序集......但是,伙计,必须有更简单的方法,对吧?我实际上是在寻找中型数据结构中的几个 bool 值。
对象的变量通过具有某些逻辑的 get/set 属性公开,并尝试进行函数调用并更新我这边可能不存在的其他对象(也就是 get 获取值我需要,但也触发了通过链接的依赖项波动的通知,我可以得到异常冒泡到我的应用程序。谈论代码味道!)。它变成了一个依赖/实现兔子洞。
edit2:制造商正在与我合作以改进他们的系统,但是当我们宣传“适用于 X”时,我们希望它只适用于 X,而不需要特定版本。特别是我们的一些客户系统受到严格的版本控制,仅更新有问题的应用程序就成为一项重大工作。
最佳答案
正如您在对问题的评论中推测的那样,SerializationSurrogate 和 SerializationBinder 可以帮助您实现目标。鉴于您只对少数属性感兴趣,您可以反序列化为代理类,您将通过枚举传递给 SerializationSurrogate 的 SerializationInfo 来填充该代理类。不幸的是,它只会让您完成部分工作。
问题是访问属性不会在序列化对象中触发任何副作用,因为您只是使用 SerializationSurrogate 访问数据——没有任何二进制代码被执行。下面的快速和肮脏的测试代码说明了这个问题:
namespace BinaryProxy
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
class TestClass
{
public bool mvalue;
public TestClass(bool value)
{
BoolValue = value;
}
public bool BoolValue
{
get
{
// won't happen
SideEffect = DateTime.Now.ToString();
return mvalue;
}
set
{
mvalue = value;
}
}
public string SideEffect { get; set; }
}
class ProxyTestClass
{
private Dictionary<string, object> data = new Dictionary<string, object>();
public Object GetData(string name)
{
if(data.ContainsKey(name))
{
return data[name];
}
return null;
}
public void SetData(string name, object value)
{
data[name] = value;
}
public IEnumerable<KeyValuePair<string, object>> Dump()
{
return data;
}
}
class SurrogateTestClassConstructor : ISerializationSurrogate
{
private ProxyTestClass mProxy;
/// <summary>
/// Populates the provided <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the object.
/// </summary>
/// <param name="obj">The object to serialize. </param>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param>
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param>
/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
throw new NotImplementedException();
}
/// <summary>
/// Populates the object using the information in the <see cref="T:System.Runtime.Serialization.SerializationInfo"/>.
/// </summary>
/// <returns>
/// The populated deserialized object.
/// </returns>
/// <param name="obj">The object to populate. </param>
/// <param name="info">The information to populate the object. </param>
/// <param name="context">The source from which the object is deserialized. </param>
/// <param name="selector">The surrogate selector where the search for a compatible surrogate begins. </param>
/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
if (mProxy == null) mProxy = new ProxyTestClass();
var en = info.GetEnumerator();
while (en.MoveNext())
{
mProxy.SetData(en.Current.Name, en.Current.Value);
}
return mProxy;
}
}
sealed class DeserializeBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
return typeof(ProxyTestClass);
}
}
static class Program
{
static void Main()
{
var tc = new TestClass(true);
byte[] serialized;
using (var fs = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(fs, tc);
serialized = fs.ToArray();
var surrSel = new SurrogateSelector();
surrSel.AddSurrogate(typeof(ProxyTestClass),
new StreamingContext(StreamingContextStates.All), new SurrogateTestClassConstructor());
using (var fs2 = new MemoryStream(serialized))
{
var formatter2 = new BinaryFormatter();
formatter2.Binder = new DeserializeBinder();
formatter2.SurrogateSelector = surrSel;
var deser = formatter2.Deserialize(fs2) as ProxyTestClass;
foreach (var c in deser.Dump())
{
Console.WriteLine("{0} = {1}", c.Key, c.Value);
}
}
}
}
}
}
在上面的示例中,TestClass
的 SideEffect
支持字段将保持为空。
如果您不需要副作用而只想访问某些字段的值,则该方法在某种程度上是可行的。否则,除了遵循 Jon Skeet 的建议之外,我想不出任何其他可行的解决方案。
关于c# - BinaryFormatter - 是否可以在没有程序集的情况下反序列化已知类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13594831/
我正在阅读 Python 文档以真正深入了解 Python 语言,并遇到了 filter 和 map 函数。我以前使用过过滤器,但从未使用过映射,尽管我在 SO 上的各种 Python 问题中都见过这
当我尝试打印 BST 的级别顺序时,这个问题提示了我。 这是一个 Pre-Order Sequence: 4, 1, 2, 3, 5, 6, 7, 8 In_order Sequence : 1, 2
我的代码在 main(序列测试;)的第一行出现错误,指出它是对 sequence::sequence() 的 undefined reference 。我无法更改 main 中的代码。有谁知道我该如何
这可能很简单,但我在通常的 latex 指南中找不到任何相关内容。在这句话中: {\em hello\/} “\/”的目的是什么? 最佳答案 这就是所谓的斜体校正。其目的是确保斜体文本后有适当的间距。
当我从 Postgresql 表中删除所有记录,然后尝试重置序列以在插入时开始一个编号为 1 的新记录时,我得到不同的结果: SELECT setval('tblname_id_seq', (SELE
在版本10.0.3中,MariaDB引入了一种称为序列的存储引擎。 其ad hoc为操作生成整数序列,然后终止。 该序列包含正整数,以降序或升序排列,并使用起始,结束和递增值。 它不允许在多个查询中
如何在 Groovy 中获取给定数字的序列,例如: def number = 169 // need a method in groovy to find the consecutive number
基本上,如果这是 .NET,它看起来像这样: ISomething { string A { get; } int B { get; } } var somethings = new List
说以下代码部分(同一块): A <= 1 A <= 2 变量 A 总是被赋值为 2 吗?还是会出现竞争条件并分配 1 或 2? 我对非阻塞赋值的理解是,由硬件在 future 分配变量 A,因此它可能
在运行 WiX 设置时,我正在寻找操作列表及其顺序。不知何故,官方网站似乎没有提供任何信息。 基本问题是我想正确安排我的自定义操作。通常我需要使用 regsvr32.exe 注册一个 DLL,而这只能
F#初学者在这里 我想创建一个类型,它是具有至少一个元素的另一种具体类型(事件)的序列。任何其他元素都可以在以后随时添加。通常在 C# 中,我会创建一个具有私有(private) List 和公共(p
作为构建过程和不断发展的数据库的一部分,我试图创建一个脚本,该脚本将删除用户的所有表和序列。我不想重新创建用户,因为这将需要比所允许的更多的权限。 我的脚本创建了一个过程来删除表/序列,执行该过程,然
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
这个问题已经有答案了: sql ORDER BY multiple values in specific order? (12 个回答) 已关闭 9 年前。 我有一个 sql 语句,我想要ORDER
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
在用java编写代码时,我需要用“],[”分割字符串。下面是我的代码。 try (BufferedReader reader = new BufferedReader(new InputStreamR
这个问题已经有答案了: Project Euler Question 14 (Collatz Problem) (8 个回答) 已关闭 9 年前。 我正在尝试查找数字的 Collatz 序列。以下
我有一个例程函数process_letter_location(const char& c, string &word)。 在我的 main 中,我声明了一系列字符串变量,如下所示: string s
我需要找到最长的多米诺骨牌链,给定一组 12 个随机挑选的多米诺骨牌。我已经递归地生成了多米诺骨牌的所有可能性(使用 0 到 12 的面值有 91 种可能性)。多米诺骨牌由一 block “砖 blo
我有这个数据结构 Seq,它继承了类 vector 但有一些额外的功能。使用这个数据结构 Seq 我有这个预定义的数据结构: typedef Seq > MxInt2d; 我现在想要一个包含多个 Mx
我是一名优秀的程序员,十分优秀!