简体   繁体   中英

Extension methods for multiple types

I have an object of type Product and type Variant . Variant and Product have the same structure, but are two different types, and so I can't make just one method to encompass both. Is it possible to make an extension method that would accept both of these types?

You cannot do that unless Product and Variant have common base class or interface.

If they have common base class or interface then you can try to write extension method for it eg

public static void MyMethod(this ICommonInterface obj) {}

Otherwise you'll have to create two separate extensions methods. You can try to extract common code to a separate method which will be called from your extension methods.

Steve,

Two possible answers to this question from a Commerce Server perspective. Depends on whether you are talking about the Core Systems API or the Commerce Foundation API. I'll address both below:

OPTION 1 : Commerce Server Core Systems API

Unfortunately, the two classes Product and Variant DO NOT share a common base class (unless you count System.Object ;-). Although Microsoft.CommerceServer.Catalog.Product inherits from Microsoft.CommerceServer.Catalog.CatalogItem, Variant does not inherit from CatalogItem or any other common base class. Variant inherits directly from System.Object.

Therefore, you cannot write an extension method that can be leveraged by both classes.

The class definition documentation for all Catalog System objects (for the Core Systems API) can be found here http://msdn.microsoft.com/en-us/library/microsoft.commerceserver.catalog(v=cs.70).aspx

在此输入图像描述

OPTION 2 : Commerce Foundation API If you are referring to Product and Variant in terms of objects being returned from calls to the Commerce Foundation, then ALL objects returned by requests using the Commerce Server Operation Service are returned as type ICommerceEntity.

If you are using concrete data types to wrap CommerceEntity, then you can still use the .ToCommerceEntity() method and you could write your extension from ICommerceEntity. The only problem with that approach is ALL classes inheriting from ICommerceEntity would be able to use the extension methods.

在此输入图像描述

View http://msdn.microsoft.com/en-us/library/dd451701.aspx for more on concrete data types in Commerce Foundation.

You could take advantage of the dynamic type:

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

Using an extension method:

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

And the sample usage:

myList.Process();

Another alternative

... is to use an object-object mapper such as AutoMapper . For the sample Product and Variant sample types above, you would have to define the members mapping with the following type which shares the common members of the 2 classes:

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

The members mapping looks like this:

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));

And you might get a working List<MyMapper> like this:

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

The Map<T> extension method:

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

From this point further, you would define your extension methods for the MyMapper type.

You can not change the Product and Variant classes, but you can subclass them and apply a interface to the subclass. This interface can be used for the extension method:

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; }
}

See: https://dotnetfiddle.net/u1JJmJ

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM