【问题标题】:Design without default constructor没有默认构造函数的设计
【发布时间】:2012-04-22 17:12:28
【问题描述】:

我想限制使用默认构造函数创建对象。因为我有如下设计:

class Program
{
    static void Main(string[] args)
    {
        BaseClass bc = new BaseClass("","");
        XmlSerializer xml = new XmlSerializer(typeof(BaseClass));
        StreamWriter sw = new StreamWriter(File.Create("c:\\test.txt"));
        xml.Serialize(sw,bc);
        sw.Flush();
        sw.Close();
    }
}
[Serializable]
public class BaseClass
{
    public string UserName, Password;
    // I don't want to create default constructor because of Authentication
    public BaseClass(string _UserName, string _Password)
    {
        UserName = _UserName;
        Password = _Password;
        f_Authenticate();
    }
    private void f_Authenticate() { }
}

public class DerivedClass:BaseClass
{
    public DerivedClass(string _UserName, string _Password) : base(_UserName, _Password)
    {
    }
}

没关系。但是当我将 BaseClass 设置为 Serializable 时,它​​会产生这个错误: Unhandled Exception: System.InvalidOperationException: ConsoleApplication1.BaseC lass cannot be serialized because it does not have a parameterless constructor.

现在我的设计正在崩溃,因为我需要有 UsernamePassword 参数,但默认构造函数正在破坏我的设计......

我该怎么办?

【问题讨论】:

标签: c# default-constructor


【解决方案1】:

创建一个私有的默认构造函数

private DerivedClass()
{
    // code
}

即使它是私有的,序列化器也会成功调用它

【讨论】:

  • 否,因为它需要一个默认构造函数,因此它会被公开访问。
  • 为了彻底彻底,您可以将 [Obsolete("Default constructor is only for serialization!", true)] 添加到该私有构造函数,以确保您不会从内部意外调用它类。
  • 这也适用于在设计器中创建的 WinForms UserControl (s)。拥有私有构造函数仍然允许在工具箱中使用它们。
【解决方案2】:

反序列化你的实例的类需要一个无参数的构造函数来创建实例,但你不必实现一个公共构造函数——只要它不需要参数,有一个privateinternal 构造函数就足够了.

顺便说一句,你也可以使用DataContractSerializer,它不需要无参数构造函数,也可以创建XML;这一直是我的首选:-)

【讨论】:

  • 我没有意识到这是有效的?我预计它需要一个公共构造函数。这确定有效吗?如果是这样,酷!
  • @TomWijsmanno,不,我的意思是调用非默认构造函数(在 OP 的示例中),但我已经删除了我的答案/评论,因为我意识到它是调用默认构造函数的序列化程序和因此它不能是私人的(我猜)
  • @Robbie - 实际上可以。它确实调用构造函数,即使它是私有的,并且它肯定使用序列化值设置私有字段,即使您没有此属性的设置器。跨度>
  • @Matten 在那种情况下,我正在取消删除我的答案,我比你快;)
【解决方案3】:
  • 您是否尝试过创建私有无参数构造函数?

  • 如果需要公开的,你可以随时评论说不应该使用它(不是最好的解决方案)

您还需要在您的 Serializable 类中创建属性。在序列化/反实现过程中不考虑变量,也不会读取或写入变量

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2018-03-09
    相关资源
    最近更新 更多