.net 如何在F中实现ISerializable#
假设您从这个存根开始:.net 如何在F中实现ISerializable#,.net,f#,constructor,iserializable,.net,F#,Constructor,Iserializable,假设您从这个存根开始: [<Serializable>] type Bounderizer = val mutable _boundRect : Rectangle new (boundRect : Rectangle) = { _boundRect = boundRect ; } new () = { _boundRect = Rectangle(0, 0, 1, 1); } new (info:SerializationInfo, context:StreamingContex
[<Serializable>]
type Bounderizer =
val mutable _boundRect : Rectangle
new (boundRect : Rectangle) = { _boundRect = boundRect ; }
new () = { _boundRect = Rectangle(0, 0, 1, 1); }
new (info:SerializationInfo, context:StreamingContext) =
{ // to do
}
interface ISerializable with
member this.GetObjectData(info, context) =
if info = null then raise(ArgumentNullException("info"))
info.AddValue("BoundRect", this._boundRect)
// TODO - add BoundRect property
[]
类型边界器=
val可变_boundRect:矩形
新建(boundRect:Rectangle)={u boundRect=boundRect;}
new()={u boundRect=Rectangle(0,0,1,1);}
新建(信息:SerializationInfo,上下文:StreamingContext)=
{//to do
}
接口ISerializable with
成员this.GetObjectData(信息、上下文)=
如果info=null,则引发(ArgumentNullException(“info”))
info.AddValue(“BoundRect”,this.\u BoundRect)
//TODO-添加BoundRect属性
问题是规范中说,“一般来说,如果类没有密封,这个构造函数应该受到保护。”F#没有受保护的关键字,那么我该怎么做呢
约束条件(由于需要完全匹配API级别的现有C#类):
F#规范指出,如果覆盖受保护的函数,则生成的函数将受到保护。这是不正确的。如果不指定可访问性,那么不管发生什么情况,结果覆盖都将是公共的(违反合同)。不幸的是,没有办法-F#没有受保护的成员。我们将在以后的版本中考虑这一点。< P>实际上受保护的修饰符不是强制执行的,而是 在反序列化期间,使用为此目的提供的构造函数将SerializationInfo传递给类。当对象被反序列化时,构造函数上的任何可见性约束都会被忽略;因此,您可以将该类标记为public、protected、internal或private 因此,这应该是可行的:
[<Serializable>]
type Bounderizer =
val mutable _boundRect : Rectangle
new (boundRect : Rectangle) = { _boundRect = boundRect ; }
new () = { _boundRect = Rectangle(0, 0, 1, 1); }
private new (info:SerializationInfo, context:StreamingContext) =
Bounderizer(info.GetValue("BoundRect", typeof<Rectangle>) :?> Rectangle)
then
printfn "serialization ctor"
interface ISerializable with
member this.GetObjectData(info, context) =
if info = null then raise(ArgumentNullException("info"))
info.AddValue("BoundRect", this._boundRect)
override this.ToString() = this._boundRect.ToString()
let x = Bounderizer(Rectangle(10, 10, 50, 50))
let ms = new MemoryStream()
let f = new BinaryFormatter()
f.Serialize(ms, x)
ms.Position <- 0L
let y = f.Deserialize(ms) :?> Bounderizer
printfn "%O" y
(*
serialization ctor
{X=10,Y=10,Width=50,Height=50}
*)
[]
类型边界器=
val可变_boundRect:矩形
新建(boundRect:Rectangle)={u boundRect=boundRect;}
new()={u boundRect=Rectangle(0,0,1,1);}
私有新建(信息:SerializationInfo,上下文:StreamingContext)=
Bounderizer(info.GetValue(“BoundRect”,typeof):?>矩形)
然后
printfn“序列化选择器”
接口ISerializable with
成员this.GetObjectData(信息、上下文)=
如果info=null,则引发(ArgumentNullException(“info”))
info.AddValue(“BoundRect”,this.\u BoundRect)
重写this.ToString()=this.\u boundRect.ToString()
设x=Bounderizer(矩形(10,10,50,50))
设ms=newmemoryStream()
设f=新的二进制格式化程序()
f、 序列化(ms,x)
ms.Position Bounderizer
打印fn“%O”y
(*
序列化选择器
{X=10,Y=10,宽度=50,高度=50}
*)
目前无法按原样使用语言执行此操作。这是可能的,我有两种方法
第一种方法是通过ILDASM、regex运行输出程序集到所需的方法声明,将所需方法中的“public”更改为“family”,然后ILASM返回。EWWWW
第二个,我正在调查,是用
[<Protected>]
[]
然后编写一个筛选器,以更改所有方法的可访问性,而不是ProtectedAttribute,然后删除该属性。这似乎没有在文件上运行正则表达式那么不体面,但我工作时的安全设置非常讨厌CCI项目源代码,因此我无法成功获取/解压缩/构建它
编辑-这是我的解决方案-我尝试了CCI,但它还没有准备好完成任务。我最终使用了以下代码:
首先是F中的一个属性#
开放系统
[<AttributeUsage(AttributeTargets.Method ||| AttributeTargets.Constructor, AllowMultiple=false, Inherited=true)>]
type MyProtectedAttribute() =
inherit System.Attribute()
[:
使用系统;
使用System.Collections.Generic;
使用System.Data.Linq;
使用系统文本;
使用单盲法;
使用Mono.Collections.Generic;
使用System.IO;
命名空间AddProtectedAttribute
{
班级计划
{
静态void Main(字符串[]参数)
{
if(args.Length!=1 | | args.Length!=3)
{
Console.Error.WriteLine(“用法:addprotectedattributeassembly-file.dll/output-output-file.dll”);
返回;
}
字符串outputFile=args.Length==3?args[2]:null;
moduledefinitionmodule=null;
尝试
{
module=ModuleDefinition.ReadModule(args[0]);
}
捕获(异常错误)
{
Console.Error.WriteLine(“无法读取程序集”+args[0]+“:”+err.Message);
返回;
}
foreach(module.Types中的类型定义类型)
{
foreach(type.Methods中的MethodDefinition方法)
{
int attrIndex=attributeIndex(method.CustomAttributes);
如果(指数<0)
继续;
方法.CustomAttributes.RemoveAt(attrIndex);
如果(方法IsPublic)
method.IsPublic=false;
如果(方法IsPrivate)
method.IsPrivate=false;
method.IsFamily=true;
}
}
if(outputFile!=null)
{
尝试
{
模块写入(输出文件);
}
捕获(异常错误)
{
Console.Error.WriteLine(“无法写入输出文件”+outputFile+“:”+err.Message);
返回;
}
}
其他的
{
outputFile=Path.GetTempFileName();
尝试
{
模块写入(输出文件);
}
捕获(异常错误)
{
Console.Error.WriteLine(“无法写入输出文件”+outputFile+“:”+err.Message);
if(File.Exists(outputFile))
文件。删除(outputFile);
返回;
}
尝试
{
Copy(outputFile,args[0]);
using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Text;
using Mono.Cecil;
using Mono.Collections.Generic;
using System.IO;
namespace AddProtectedAttribute
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 1 || args.Length != 3)
{
Console.Error.WriteLine("Usage: AddProtectedAttribute assembly-file.dll /output output-file.dll");
return;
}
string outputFile = args.Length == 3 ? args[2] : null;
ModuleDefinition module = null;
try
{
module = ModuleDefinition.ReadModule(args[0]);
}
catch (Exception err)
{
Console.Error.WriteLine("Unable to read assembly " + args[0] + ": " + err.Message);
return;
}
foreach (TypeDefinition type in module.Types)
{
foreach (MethodDefinition method in type.Methods)
{
int attrIndex = attributeIndex(method.CustomAttributes);
if (attrIndex < 0)
continue;
method.CustomAttributes.RemoveAt(attrIndex);
if (method.IsPublic)
method.IsPublic = false;
if (method.IsPrivate)
method.IsPrivate = false;
method.IsFamily = true;
}
}
if (outputFile != null)
{
try
{
module.Write(outputFile);
}
catch (Exception err)
{
Console.Error.WriteLine("Unable to write to output file " + outputFile + ": " + err.Message);
return;
}
}
else
{
outputFile = Path.GetTempFileName();
try
{
module.Write(outputFile);
}
catch (Exception err)
{
Console.Error.WriteLine("Unable to write to output file " + outputFile + ": " + err.Message);
if (File.Exists(outputFile))
File.Delete(outputFile);
return;
}
try
{
File.Copy(outputFile, args[0]);
}
catch (Exception err)
{
Console.Error.WriteLine("Unable to copy over original file " + outputFile + ": " + err.Message);
return;
}
finally
{
if (File.Exists(outputFile))
File.Delete(outputFile);
}
}
}
static int attributeIndex(Collection<CustomAttribute> coll)
{
if (coll == null)
return -1;
for (int i = 0; i < coll.Count; i++)
{
CustomAttribute attr = coll[i];
if (attr.AttributeType.Name == "MyProtectedAttribute")
return i;
}
return -1;
}
}
}