有人可以对以二进制形式序列化数据的危险给出合理的解释,或者参考一个好的解释吗?“使用 BinaryFormatter 和相关类型的反序列化风险”中给出的“它本质上是危险的”或“它无法安全处理”之类的论点并没有说服我。
主页
/
user-510054
rotabor's questions
我决定使用CRTP重做房间中对象的 OOP 实现。
using System;
using System.Linq;
using System.Reflection;
using System.Collections;
using System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Method)]
public class ActionItemAttribute : Attribute {
public string ActionName { get; set; }
public string ActionDescription { get; set; }
}
// если сделать реализацию немножко по-другому, то без этого класса можно обойтись
public class ActionItem {
public IList<CustomAttributeNamedArgument> Attributes { get; init; }
public string MethodName { get; init; }
public ActionItem(string mn, IList<CustomAttributeNamedArgument> il) { MethodName = mn; Attributes = il; }
}
class ItemBase {
public string Name { get; init; }
public ItemBase(string nm) => Name = nm;
// это вспомогательная функция, можно и без неё
protected string GetActionDescription([CallerMemberName] string callingMethod = "")
=> (GetType().GetMethod(callingMethod)!.GetCustomAttribute(typeof(ActionItemAttribute)) as ActionItemAttribute)
?.ActionDescription!;
// это нужно
public virtual List<ActionItem> ActionableItems {get => null; }
// это нужно
public object Act(string action) {
Console.Write($" {((ActionItemAttribute)Attribute.GetCustomAttribute(GetType().GetMethod(action), typeof(ActionItemAttribute), true)).ActionName}: ");
if (GetType().GetMethod(action).ReturnType != typeof(void))
return GetType().GetMethod(action).Invoke(this, new object[] { });
else { GetType().GetMethod(action).Invoke(this, new object[] { }); return null; }
}
// каждое действие должно быть помечено таки атрибутом, он может быть и пустой,
// если дополнительная информация не нужна
[ActionItem(ActionName = "Взять", ActionDescription = "Взять предмет")]
public virtual void Take() => Console.WriteLine("Не забудь вернуть обратно.");
[ActionItem(ActionName = "Вытащить содержимое", ActionDescription = "Вытащить содержимое из предмета")]
public virtual object GetContent() { Console.WriteLine("Аааа, ломать не нужно!!!"); return null; }
}
class Item<TSelf> : ItemBase where TSelf : Item<TSelf> {
protected static List<ActionItem> _sactionlist;
// это нужно для построения спика действий
protected static List<ActionItem> GetActionList(Type T) =>
T.GetMethods().Where(w => w.CustomAttributes
.Where(w => w.AttributeType == typeof(ActionItemAttribute)).Any())
.Select(s => new ActionItem(s.Name, s.CustomAttributes
.Single(s => s.AttributeType == typeof(ActionItemAttribute)).NamedArguments))
.ToList();
public override List<ActionItem> ActionableItems { get => _sactionlist; }
public Item(string nm) : base(nm) { }
// это вспомогательная функция, можно и без неё
}
class WindowItem : Item<WindowItem> {
static WindowItem() => _sactionlist = GetActionList(MethodBase.GetCurrentMethod().DeclaringType);
public WindowItem(string name) : base(name) { }
[ActionItem(ActionName = "Открыть", ActionDescription = "Открыть окно")]
public void Open() => Console.WriteLine(GetActionDescription());
[ActionItem(ActionName = "Закрыть", ActionDescription = "Закрыть окно")]
public void Close() => Console.WriteLine(GetActionDescription());
[ActionItem(ActionName = "Взять", ActionDescription = "Взять предмет")]
public override void Take() => Console.WriteLine("Ага, попробуй возьми.");
}
class Cloth : Item<Cloth> {
static Cloth() => _sactionlist = GetActionList(MethodBase.GetCurrentMethod().DeclaringType);
public Cloth(string name) : base(name) { }
public void Wash() => Console.WriteLine("Постирать тряпку.");
}
class Box : Item<Box> {
static Box() => _sactionlist = GetActionList(MethodBase.GetCurrentMethod().DeclaringType);
public Box(string name) : base(name) { }
[ActionItem(ActionName = "Вытащить содержимое", ActionDescription = "Вытащить содержимое из коробки")]
public override object GetContent() => new object[] { "большие солнечные очки", "звонок от велосипеда", "вобла" };
}
class Room : IEnumerable {
List<ItemBase> _items;
public Room() => _items = new List<ItemBase>();
public void Add(ItemBase i) => _items.Add(i);
public IEnumerator GetEnumerator() => _items.GetEnumerator();
}
internal class Program {
static void ConsoleWriteLine(object o) =>
Console.WriteLine(o is IEnumerable ? String.Join("; ", (object[])o) : o);
static void Main() {
var room = new Room { new WindowItem("Переднее окно"), new Cloth("Тряпка для доски"), new Box("Шкатулка") };
foreach (ItemBase itm in room) {
Console.WriteLine($"Предмет: {itm.Name}");
foreach (var method in itm.ActionableItems)
if (itm.GetType().GetMethod(method.MethodName).ReturnType != typeof(void))
ConsoleWriteLine(itm.Act(method.MethodName));
else itm.Act(method.MethodName);
}
}
}
我将 _sactionlist 字段移至基类,但我无法摆脱每个后代中的静态构造函数(静态 WindowItem、静态 Cloth、静态 Box)。还有出路吗?
Int64 作为两个 Int32 输入。是否有可能以某种方式获得十进制形式的字符串表示形式的原始数字,仅具有 Int32 和 + - * / MOD 操作、位操作、移位、循环、条件运算符?例如,您可以在一个 Int32 中获取低 9 位十进制数字,在另一个 Int32 中获取高十进制数字,并且可以忽略 4-5 位二进制数字的损失。
例:原数 78542365896558 输入为 18287(高位双字)和 298954606(低位双字)。输出是一个字符串或两个数字 78542 和 365896558。
它就是这样一台计算机——工业PLC。结构化文本编程语言是为了提供信息。真正的 - 只有浮点数(单精度)。有实数数组。还有一种字符串数据类型,只有字符串常量、连接以及数字到字符串的转换,反之亦然。SELSTR 函数 - 按索引选择五行之一。
结果必须表示为两个(或更多,如果需要)Int32(如上所述)或字符串。
您可以使用 c*(c、c#、c++)或 Python 对该算法进行建模。
我想了想,最后决定只离线使用 - 对于顶层接口,我编写了一个 COM 库,它使用两个 Int32 返回一个字符串。我想在控制器中实现这个。
如果有人对这项任务感兴趣,我可以将其用于 NNN 积分竞赛。