C# 转换到不排除表单成员的接口

C# 转换到不排除表单成员的接口,c#,json,interface,casting,C#,Json,Interface,Casting,我正在用C#开发一个应用程序,它在表单上声明了一个接口: public partial class frmProjectForm : Form, IProjectInfo { } public interface IProjectInfo { string ProjectName { get; set; } string ProjectTitle { get; set; } string ProjectDescription { get; set; } str

我正在用C#开发一个应用程序,它在表单上声明了一个接口:

public partial class frmProjectForm : Form, IProjectInfo
{

}

public interface IProjectInfo
{
    string ProjectName { get; set; }
    string ProjectTitle { get; set; }
    string ProjectDescription { get; set; }
    string ProjectAuthor { get; set; }
    string ProjectCopyright { get; set; }
    string ProjectTrademark { get; set; }
    string ProjectCreationDate { get; set; }
    string ProjectVersion { get; set; }
    string ProjectFileName { get; }
    string ProjectFilePath { get; }
    string FullProjectPath { get; }
}
在应用程序中的某个地方,我希望执行以下操作:

frmProjectForm f = new frmProjectForm();
f.ShowDialog(this);
...
...
IProjectInfo getProjectInfoMembersOnly = (IProjectInfo)f;

// persist the IProjectInfo members to JSON
string project = JsonConvert.SerializeObject( getProjectInfoMembersOnly );
JsonConvert.SerializeObject
方法正在崩溃,并抱怨Button控件上存在一些自引用循环。转换操作并不排除表单,我不知道为什么,因为我只希望接口转换只返回接口成员


我做错了什么?

序列化代码处理对象的实际类型,而不是作为参数传递的类型,这在我看来很正常(函数甚至可能接受类型为
object
的参数,而不是泛型函数
序列化对象(T obj)

如果您希望对对象进行切片,恐怕您必须自己执行切片,方法是创建一个实现接口的对象并仅复制其成员

public class ProjectInfo : IProjectInfo
{
    public string ProjectName { get; set; }
    public string ProjectTitle { get; set; }
    public string ProjectDescription { get; set; }
    public string ProjectAuthor { get; set; }
    public string ProjectCopyright { get; set; }
    public string ProjectTrademark { get; set; }
    public string ProjectCreationDate { get; set; }
    public string ProjectVersion { get; set; }
    public string ProjectFileName { get; private set; }
    public string ProjectFilePath { get; private set; }
    public string FullProjectPath { get; private set; }

    public ProjectInfo(IProjectInfo src)
    {
        this.ProjectName = src.ProjectName;
        this.ProjectTitle = src.ProjectTitle;
        this.ProjectDescription = src.ProjectDescription;
        this.ProjectAuthor = src.ProjectAuthor;
        this.ProjectCopyright = src.ProjectCopyright;
        this.ProjectTrademark = src.ProjectTrademark;
        this.ProjectCreationDate = src.ProjectCreationDate;
        this.ProjectVersion = src.ProjectVersion;
        this.ProjectFileName = src.ProjectFileName;
        this.ProjectFilePath = src.ProjectFilePath;
        this.FullProjectPath = src.FullProjectPath;
    }
}
然后你可以这样使用它:

frmProjectForm f = new frmProjectForm();
f.ShowDialog(this);
...
...
IProjectInfo getProjectInfoMembersOnly = new ProjectInfo(f); //I only changed this line

// persist the IProjectInfo members to JSON
string project = JsonConvert.SerializeObject( getProjectInfoMembersOnly );

如果您只使用接口进行序列化(您的问题不清楚),那么您根本不需要接口。JSON.NET提供了一些属性来标记哪些字段应该序列化。即使您将接口用于其他用途,也没有理由不能这样定义类:

// Use optin so you don't have to worry about fields generated by the designer.
[JsonObject(MemberSerialization.OptIn)]
public partial class frmProjectForm : Form
{
    [JsonProperty]
    public string ProjectName { get; set; }
    [JsonProperty]
    public string ProjectTitle { get; set; }
    [JsonProperty]
    public string ProjectDescription { get; set; }
    [JsonProperty]
    public string ProjectAuthor { get; set; }
    [JsonProperty]
    public string ProjectCopyright { get; set; }
    [JsonProperty]
    public string ProjectTrademark { get; set; }
    [JsonProperty]
    public string ProjectCreationDate { get; set; }
    [JsonProperty]
    public string ProjectVersion { get; set; }
    [JsonProperty]
    public string ProjectFileName { get; }
    [JsonProperty]
    public string ProjectFilePath { get; }
    [JsonProperty]
    public string FullProjectPath { get; }

    // . . . Other properties, buttons, and form fields
}

然后,当调用
JSONConvert.SerializeObject()
时,只有标记为
JsonProperty
的字段才会被序列化。

我不太确定,但我认为,在序列化时,仅将实例强制转换到接口不会隐藏实例属性……您仍在序列化该实例。如果您只需要接口属性,为什么要继承表单?@AMember我实际上并没有继承表单——它是一个继承接口的表单。我想创建一个标准化的表单,在这里我可以使用
IProjectInfo
接口作为方法参数,而不是指定具体的表单实例。我认为这是一个很好的解决方案。我已经有了一个继承了
IProjectInfo
的具体类,所以我将在你的切片建议中使用它。但是在看到@tandrewnichols的答案后,我认为它比我的要好得多。