Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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
为什么C#DataMember属性允许私有字段和属性的序列化?_C#_Oop - Fatal编程技术网

为什么C#DataMember属性允许私有字段和属性的序列化?

为什么C#DataMember属性允许私有字段和属性的序列化?,c#,oop,C#,Oop,如果将DataMember属性添加到任何字段或属性(包括private字段或属性),它们仍将被序列化。Microsoft明确指出这一点: 您可以将DataMemberAttribute应用于私有字段或属性。请注意,该成员返回的数据(即使是私有的)将被序列化和反序列化,因此恶意用户或进程可以查看或拦截 例如: public class MyClass { [DataMember(Name = "pushed_at")] private string JsonDate { get;

如果将
DataMember
属性添加到任何字段或属性(包括private字段或属性),它们仍将被序列化。Microsoft明确指出这一点:

您可以将DataMemberAttribute应用于私有字段或属性。请注意,该成员返回的数据(即使是私有的)将被序列化和反序列化,因此恶意用户或进程可以查看或拦截

例如:

public class MyClass
{
    [DataMember(Name = "pushed_at")] 
    private string JsonDate { get; set; } //PRIVATE!

    [IgnoreDataMember]
    public DateTime PushedAt
    {
        get { return JsonDate; }
    }
}

var serializer = new DataContractJsonSerializer(typeof(List<MyClass>));
var streamTask = client.GetStreamAsync("https://api.mysite.com/hit");
var classes = serializer.ReadObject(await streamTask) as List<MyClass>;

foreach (var myClass in classes)
{
    Console.WriteLine(myClass.JsonDate); //Error because private
    Console.WriteLine(myClass.PushedAt); //Ok and shows serialized data
}
公共类MyClass
{
[DataMember(Name=“pushd_at”)]
私有字符串JsonDate{get;set;}//private!
[IgnoreDataMember]
公共日期时间推送
{
获取{return JsonDate;}
}
}
var serializer=newdatacontractjsonserializer(typeof(List));
var streamTask=client.GetStreamAsync(“https://api.mysite.com/hit");
var classes=serializer.ReadObject(等待streamTask)作为列表;
foreach(类中的var myClass)
{
Console.WriteLine(myClass.JsonDate);//错误,因为私有
Console.WriteLine(myClass.PushedAt);//确定并显示序列化数据
}
为什么这有意义?自封装的原理不是比序列化更基本吗?
DataMember
属性真的提供了对类外私有属性的访问权限,还是我遗漏了一些东西

如果将
JsonDate
设置为公共,并将其设置为
private
setter,也会发生同样的情况

自封装的原理不是比序列化更基本吗

不,“纯”编程原则原则上很好,但有时你只需要完成一些事情

如果这包括反序列化到一个私有成员,不管出于什么原因,.NET设计团队显然决定他们不会阻止你这么做,即使这意味着有更多干净的代码

考虑到你所说的,他们是故意做出这个选择的

自封装的原理不是比 序列化

序列化使用反射进行,因此我们可以更改您的问题:

自封装的原理不是比 反思


答案也是如此,为什么这样做有意义呢?,因为它是有文档记录的。这就是选择加入。所以,如果你不想要它,就不要使用它。您可以通过其他方式(例如反射)访问私人成员,因此这不是对安全性的根本违反。@mjwills这是一个非常糟糕的原因。试图理解为什么他们决定允许重写私有成员和属性等基本内容。这些私有成员通常是对象状态的组成部分。如果它们无法序列化,那么你就永远无法真正序列化任何东西(只有公共成员的对象除外),因为反序列化它们会给你不完整的对象或状态无效的对象——因为私有成员会因序列化而丢失。我的观点是说“它已被记录”是没有帮助的。我不是一个有20年经验的超级明星开发人员,我不知道更好的实现方法,这就是为什么我要求比我聪明的人给我动力。仅仅因为我没有更好的方法来实现它并不意味着没有更好的方法,也不意味着没有更好的方法来实现循环漏洞。我猜您是说,通过这种方式允许访问私有字段/属性是一种获得访问权限的方法,否则您将无法访问这些字段/属性,同时使它们对类的所有其他用户都是私有的?因此,如果您被迫将序列化所需的所有内容都公开,这会更好吗?在您的示例中,您将拥有两个具有相同含义但返回类型不同的公共属性。我打赌这会打破另一个设计原则。