C#中类型之间的隐式转换

时间:2011-08-17 21:23:06

标签: c# .net json implicit-conversion

我有以下业务对象:

    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}

问题:我应该为这些新类型编写类似于上述示例的隐式转换 - ProductForExport1ProductForExport2(所以基本上创建100.000 + 100.000个新对象)

某种程度上,我可以用原始类型的一些魔法“隐藏”不需要的属性而无需创建新实例吗?

感谢,

5 个答案:

答案 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
    });
}