Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何在F中实现ISerializable#_.net_F#_Constructor_Iserializable - Fatal编程技术网

.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#类):

  • 必须实现ISerializable
  • 构造函数必须受到保护
  • 编辑-有趣的额外信息
    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;
            }
        }
    }