我有以下业务对象:
public abstract class Product
{
public int Id { get; set; }
public bool OnStock { get; set; }
}
public class ProductForImport : Product
{
public int ImportId { get; set; }
}
public class ProductForExport : Product
{
public int ExportId { get; set; }
public bool IsExportable { get; set; }
public bool IsUsable { get; set; }
public string OtherParam {get; set;}
public static implicit operator ProductForExport(ProductForImport pfi)
{
ProductForExport p = new ProductForExport();
p.Id = pfi.Id;
p.IsExportable = true;
p.ExportId = 0;
return p;
}
}
所以我可以在两种类型之间进行转换:
static void Main(string[] args)
{
ProductForExport pfe = new ProductForExport();
pfe.Id = 1;
pfe.OnStock = true;
ProductForImport pfi = new ProductForImport();
pfi.ImportId = 200;
ProductForExport pfe2 = (ProductForExport)pfi;
}
这个工作正常。
我有100.000个ProductsForImport项目。 如果我理解正确,如果我将它们转换为ProductsForExport项目,我将在内存中有100.000 +100.000项 - 这是合理的。
我的问题是:我必须通过JSON服务发送这些“ProductForExport”对象,每个服务只需要每种类型的属性的某些子集:
servicecall1应该返回ProductForExport1{ExportId,IsExportable}
servicecall2应该返回ProductForExport2{ExportId,IsUsable}
问题:我应该为这些新类型编写类似于上述示例的隐式转换 - ProductForExport1
和ProductForExport2
(所以基本上创建100.000 + 100.000个新对象)
或
某种程度上,我可以用原始类型的一些魔法“隐藏”不需要的属性而无需创建新实例吗?
感谢,
湾
答案 0 :(得分:3)
如果您需要实体的这种解耦和分离 - 您可以创建DTO对象以及每个业务对象,并使用DTO与Service进行通信。 但是如果你有很多商业实体,可以考虑采用其他方法来避免维护地狱。
public sealed class ExportProductDto
{
public(ProductForExport exportProduct)
{
// initialize fields
this.ExportId = exportProduct.ExportId;
}
public int ExportId { get; private set; }
}
顺便说一句, 运算符过载的过度杀伤解决方案,使用Adapter pattern在产品类型之间进行转换
要解除对实体的适应,请实现以下界面:
public interface IProductAdapter<TImport, TExport>
{
TImport ToImportProduct(TExport exportProduct);
TExport ToExportProduct(TImport importProduct);
}
或其他适配器方法:
// Implement this interface for ProductForImport class
// public class ProductForImport : IExportProductAdapter, Product
public interface IExportProductAdapter
{
ProductForExport ToExportProduct();
}
// Implement this interface for ProductForExport class
// public class ProductForExport : IImportProductAdapter, Product
public interface IImportProductAdapter
{
ProductForImport ToImportProduct();
}
编辑:回复评论
// An example of IExportProductAdapter adapter implementation
public sealed class ProductForImport : Product, IExportProductAdapter
{
public int ImportId { get; set; }
public ProductForExport ToExportProduct()
{
ProductForExport p = new ProductForExport();
p.Id = this.Id;
p.IsExportable = true;
p.ExportId = 0;
return p;
}
}
然后而不是:
ProductForExport pfe2 = (ProductForExport)pfi;
你可以这样做:
ProductForExport pfe2 = pfi.ToExportProduct();
答案 1 :(得分:3)
我会创建轻量级对象,专门用于仅通过必需的字段返回服务。然后使用Automapper或类似的东西来映射它们。
如果可以避免,我不建议使用运算符重载。我已经看到许多问题,开发人员在调用操作符重载时发生了意外,并发生了意外情况。
答案 2 :(得分:2)
如果您使用的是WCF,则可以将IgnoreDataMemberAttribute
应用于您不希望序列化的属性。
答案 3 :(得分:1)
查看ScriptIgnoreAttribute以从json序列化中排除属性。
答案 4 :(得分:1)
它花了我一些读数,但我不认为你的问题与隐式转换有关,就像如何通过json发送数据一样吗?
如果您拥有Import或Export对象的对象集合,则可以使用JavaScriptSerilizer和一些匿名类型来对您发送的数据进行切片和切块。
您可以使用Linq在集合中选择对象的特定属性,并定义一个匿名类型“on-the-fly”以序列化为json字符串,如下所示:
List<ProductForExport> exportList; //the list to export
JavaScriptSerializer jss = new JavaScriptSerializer();
string output = string.Empty;
output = jss.Serialize(new
{
isExportable = True, //static named properties
iTotalProducts = exportList.Count, //dynamic values
productDataArray = exportList //all data in an array object
});
//Or build the result using just a few properties of the collection:
foreach (ExportProduct exProd in exportList)
{
output += jss.Serialize(new
{
exProd.IsExportable,
exProd.ExportID
});
}