多种类型的扩展方法

时间:2013-10-30 16:04:36

标签: c# microsoft-commerce-server

我有Product类型的对象,并且输入VariantVariantProduct具有相同的结构,但是有两种不同的类型,因此我不能只使用一种方法来包含这两种类型。是否可以制作一个可以接受这两种类型的扩展方法?

4 个答案:

答案 0 :(得分:6)

除非ProductVariant具有公共基类或接口,否则不能这样做。

如果他们有共同的基类或接口,那么你可以尝试为它编写扩展方法,例如

public static void MyMethod(this ICommonInterface obj) {}

否则,您将不得不创建两个单独的扩展方法。您可以尝试将公共代码提取到一个单独的方法,该方法将从您的扩展方法中调用。

答案 1 :(得分:1)

史蒂夫,

从Commerce Server的角度来看这个问题的两个可能的答案。取决于您是在谈论Core Systems API还是Commerce Foundation API。我将在下面解决两个问题:

选项1:Commerce Server核心系统API

不幸的是,Product和Variant这两个类不共享一个公共基类(除非你计算System.Object ;-)。虽然Microsoft.CommerceServer.Catalog.Product继承自Microsoft.CommerceServer.Catalog.CatalogItem,但Variant不会从CatalogItem或任何其他公共基类继承。 Variant直接从System.Object继承。

因此,您无法编写可由两个类使用的扩展方法。

可以在此处找到所有目录系统对象(针对Core Systems API)的类定义文档http://msdn.microsoft.com/en-us/library/microsoft.commerceserver.catalog(v=cs.70).aspx

enter image description here

选项2:Commerce Foundation API 如果您在从对Commerce Foundation的调用返回的对象方面引用Product和Variant,则使用Commerce Server Operation Service的请求返回的所有对象将作为类型ICommerceEntity返回。

如果您使用具体数据类型来包装CommerceEntity,那么您仍然可以使用.ToCommerceEntity()方法,并且可以从ICommerceEntity编写扩展。该方法的唯一问题是从ICommerceEntity继承的所有类都可以使用扩展方法。

enter image description here

查看http://msdn.microsoft.com/en-us/library/dd451701.aspx以获取有关Commerce Foundation中具体数据类型的更多信息。

答案 2 :(得分:0)

您可以利用dynamic类型:

using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var myList = new object[] { 
            new Product(){Id=1},
            new Variant(){Id=1}
        };
        Process(myList);
    }

    static void Process(object[] myList)
    {
        foreach (dynamic item in myList)
        {
            item.Id += 1;
        }
    }
}

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Foo { get; set; }
}
class Variant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Bar { get; set; }
}
pub

使用扩展方法:

public static class X
{
    public static void Process(this object[] myList)
    {
        foreach (dynamic item in myList)
        {
            item.Id += 1;
        }
    }
}

样本用法:

myList.Process();

另一种选择

...是使用对象 - 对象映射器,例如AutoMapper。对于上面的示例ProductVariant样本类型,您必须使用以下类型定义成员映射,该类型共享2个类的公共成员:

public class MyMapper
{
    public int Id { get; set; }
    public string Name { get; set; }
}

成员映射如下所示:

Mapper.CreateMap<Product, MyMapper>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name));
Mapper.CreateMap<Variant, MyMapper>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name));

你可能会得到这样的List<MyMapper>

var myMapperList = myList.Select(item => item.Map()).ToList();

Map<T>扩展方法:

public static MyMapper Map<T>(this T obj)
{
    return (MyMapper)Mapper.Map(obj, obj.GetType(), typeof(MyMapper));
}

从这一点开始,您将为MyMapper类型定义扩展方法。

答案 3 :(得分:0)

您无法更改Product和Variant类,但您可以将它们子类化并将接口应用于子类。此接口可用于扩展方法:

using System;

public class Program
{
    public static void Main()
    {
        var p = new MyProduct();
        p.Name = "test";
        Console.WriteLine(p.GetName());
    }
}


public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Foo { get; set; }
}
public class Variant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Bar { get; set; }
}

public class MyProduct: Product, IType {
}

public class MyVariant: Variant, IType {
}


public static class Extensions {
    public static string GetName(this IType type){
        return type.Name;
    }
}

public interface IType {
    string Name {get; set; }
}

请参阅:https://dotnetfiddle.net/u1JJmJ