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?
Extension methods for multiple types
5.1k Views Asked by Stephen K AtThere are 4 best solutions below

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.

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 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; }
}
You cannot do that unless
Product
andVariant
have common base class or interface.If they have common base class or interface then you can try to write extension method for it e.g.
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.