我有一个 typeProduct
和 type的对象Variant
。 Variant
并且Product
具有相同的结构,但是是两种不同的类型,所以我不能只用一种方法来涵盖两者。是否可以创建一个可以接受这两种类型的扩展方法?
4 回答
Product
除非并且Variant
具有通用的基类或接口,否则您不能这样做。
如果他们有共同的基类或接口,那么你可以尝试为它编写扩展方法,例如
public static void MyMethod(this ICommonInterface obj) {}
否则,您将不得不创建两个单独的扩展方法。您可以尝试将通用代码提取到一个单独的方法中,该方法将从您的扩展方法中调用。
史蒂夫,
从 Commerce Server 的角度来看,这个问题有两个可能的答案。取决于您是在谈论核心系统 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。
因此,您不能编写两个类都可以使用的扩展方法。
所有目录系统对象(用于核心系统 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 继承的所有类都可以使用扩展方法。
有关 Commerce Foundation 中具体数据类型的更多信息,请查看http://msdn.microsoft.com/en-us/library/dd451701.aspx 。
您可以利用以下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
类型定义扩展方法。
您不能更改 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; }
}