【问题标题】:Cascading extension methods for multiple interfaces?多个接口的级联扩展方法?
【发布时间】:2012-01-24 21:07:56
【问题描述】:

我的对象可以实现多个接口。我想知道是否有一种方法可以在使用相同的方法名称时将一个扩展方法“级联”到另一个扩展方法中。我可能看错了,但这里有一个例子:

public interface IBaseDto
{
     int Id {get;set;}
     string CreatedByFullName {get;set;}
}

public interface IDocumentDto
{
     List<ContactDto> Subscriptions {get;set;}
}

public class ContactDto: IBaseDto
{
     public int Id {get;set;}
     public string CreatedByFullName {get;set;}
     public string FirstName {get; set}
     public string LastName {get;set;}
}

public class MeetingDto: IDocumentDto
{
     public int Id {get;set;}
     public string CreatedByFullName {get;set;}
     public List<ContactDto> Subscriptions {get;set;}
}

所以,假设我想使用扩展方法将 DTO 转换为实体。一个例子是MeetingDto.ToEntity();

我正在考虑是否可以为IBaseDto 编写扩展方法的一部分,为IDocumentDto 编写另一个扩展方法,然后为每个具体实现编写它们自己的属性。当我调用MeetingDto.ToEntity()时,它会先点击会议扩展方法并调用IDocumentDto版本,填写它需要的内容,然后IDocumentDto会调用IBaseDto。我希望这是有道理的。

更新:

我想出了这个,效果很好:

public static TBaseDto ToEntity<TBridgeDto>(this TBaseDto dto) where TBaseDto: IBaseDto
        {
...            
return dto;
        }


        public static TDocumentDto ToEntity<TDocumentDto>(this TDocumentDto dto, IDocumentDto currentDto) where TDocumentDto : IDocumentDto
        {
...            
return dto.ToEntity();
        }

        public static MeetingDto ToEntity(this RfiDto dto)
        {
...            
return dto.ToEntity(dto)

        }

【问题讨论】:

  • 为什么要使用扩展方法?您是否认为您的 DTO 更干净,因为 ToEntity() 方法是在其他地方定义的?您对 的描述中的其他所有内容似乎都表明,每个子类覆盖的 IBaseDTO 上的 ToEntity() 方法是理想的。顺便说一句,MeetingDto 也应该从 IBaseDTO 继承吗?
  • automapper 可能是你的朋友。
  • @DanielA.White,我正在使用 Automapper 来生成我的 DTO,但是从 DTO 到实体的转换是有问题的。此外,还有一些我们正在做的映射属性之外的事情。
  • @perfectist,我们已经有很多基础设施,创建扩展方法似乎比更新我们所有的 DTO 更容易。

标签: c# extension-methods


【解决方案1】:

像这样?

public static class Helper
{
    public static void ToEntity(this MeetingDto source)
    {
        Console.WriteLine ("MeetingDto.ToEntity");
        //Do Stuff
        (source as IDocumentDto).ToEntity();
    }

    public static void ToEntity(this ContactDto source)
    {
        Console.WriteLine ("ContactDto.ToEntity");
        //Do Stuff
        (source as IBaseDto).ToEntity();
    }

    public static void ToEntity(this IDocumentDto source)
    {
        Console.WriteLine ("IDocumentDto.ToEntity");
        //Do Stuff
        foreach (var element in source.Subscriptions)
        {
            element.ToEntity();
        }
    }

    public static void ToEntity(this IBaseDto source)
    {
        Console.WriteLine ("IBaseDto.ToEntity");
        //Do Stuff        
    }
}

【讨论】:

  • 与我想出的非常相似。不错!
【解决方案2】:

是的,您可以.....只需投射到您想要的界面...

例如

 interface I1
    {
        int Id { get; set; }
    }

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

    public class Blah : I1, I2
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    static class ExtendIt
    {
        public static void ToEntity(this I1 x)
        {
            x.Id = 1;
        }

        public static void ToEntity(this I2 x)
        {
            x.Name = "hello";
        }

        public static void ToEntity(this Blah x)
        {
            (x as I1).ToEntity();
            (x as I2).ToEntity();
        }


    }

【讨论】:

    【解决方案3】:

    扩展方法是静态的,因此它们不能被继承覆盖。

    如果您希望它应用于每个元素,为什么不让两个接口都使用您的 ToEntity 方法实现第三个接口?

    如果您无法修改这些类,请考虑使用类似于 IConverer 接口的东西。有一个带有方法的接口,该方法接受……某物,并返回一个实体。 (它可以是通用的。)通过这种方式,您可以分离出将每种类型转换为实体的代码,就像使用扩展方法一样。

    【讨论】:

      猜你喜欢
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多