我有Product
类型的对象,并且输入Variant
。 Variant
和Product
具有相同的结构,但是有两种不同的类型,因此我不能只使用一种方法来包含这两种类型。是否可以制作一个可以接受这两种类型的扩展方法?
答案 0 :(得分:6)
除非Product
和Variant
具有公共基类或接口,否则不能这样做。
如果他们有共同的基类或接口,那么你可以尝试为它编写扩展方法,例如
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
选项2:Commerce Foundation API 如果您在从对Commerce Foundation的调用返回的对象方面引用Product和Variant,则使用Commerce Server Operation Service的请求返回的所有对象将作为类型ICommerceEntity返回。
如果您使用具体数据类型来包装CommerceEntity,那么您仍然可以使用.ToCommerceEntity()方法,并且可以从ICommerceEntity编写扩展。该方法的唯一问题是从ICommerceEntity继承的所有类都可以使用扩展方法。
查看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。对于上面的示例Product
和Variant
样本类型,您必须使用以下类型定义成员映射,该类型共享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; }
}