我正在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
的参数,而不是泛型函数SerializeObject<T>(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
的字段才会被序列化。