假设你从这个存根开始:
[<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问题是规范说,“一般来说,如果类没有密封,这个构造函数应该受到保护。”F#没有受保护的关键字--那么我该如何做呢?
约束(由于需要在API级别完全匹配现有的C#类):
编辑-有趣的额外信息,F#规范说,如果您覆盖一个受保护的函数,结果函数将受到保护。这是错误的。如果不指定可访问性,则不管发生什么(违反约定),结果的覆盖都将是公开的。
发布于 2010-07-24 10:19:16
目前无法按原样使用该语言来完成这一任务。这样做是可能的,我有两种方法。
第一种方法是通过ILDASM运行输出程序集,将其正则化为所需的方法声明,将所需方法中的“public”更改为“家族”,然后将其返回。哇哦。
第二个,我正在调查的,是用
[<Protected>]然后用CCI编写一个过滤器,以更改所有方法的可访问性,而不是拥有ProtectedAttribute,然后删除该属性。这似乎比在文件上运行regex不太合适,但是我在工作中的安全设置非常讨厌CCI项目源代码,所以我无法成功地获取/解压缩/构建它。
编辑-这是我的解决方案-我尝试了CCI,但它还没有准备好的任务。我最后使用了塞西尔,最后得到了以下代码:
首先是F#中的一个属性
开放系统
[<AttributeUsage(AttributeTargets.Method ||| AttributeTargets.Constructor, AllowMultiple=false, Inherited=true)>]
type MyProtectedAttribute() =
inherit System.Attribute()然后是下面的应用程序,它是塞西尔的客户端
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;
}
}
}最后,用MyProtectedAttribute来装饰您希望受到保护的方法,并运行C#应用程序作为构建后的步骤。
发布于 2010-07-23 20:52:41
不幸的是,没有办法- F#没有受保护的成员。我们将在今后的版本中考虑这一点。
发布于 2010-07-23 21:03:52
实际上,受保护的修饰符不是强制执行的,而是一个推荐。
在反序列化期间,使用为此目的提供的构造函数将SerializationInfo传递给类。当对象反序列化时,放置在构造函数上的任何可见性约束都会被忽略;因此,可以将类标记为公共、受保护、内部或私有的。
所以这应该是可行的:
[<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}
*)https://stackoverflow.com/questions/3319274
复制相似问题