c#如何在泛型方法中使用自定义扩展

时间:2014-03-06 03:47:58

标签: c# generics interface

我有一些复制的代码,因此希望制作一个通用的方法。我有一个常用的命名扩展方法,我想在方法中使用。通常,如果它不是扩展方法,我会创建一个接口,通过该接口限制泛型参数类,然后您可以使用该常用方法。但这不适用于扩展方法。

这是我的通用方法:

public ActionConfirmation<string> CreateUpdateEntity<TExternalEntity, TQuickbooksEntity>(TExternalEntity entity, CompanyPreferencesFinancialsSystemCommon preferences)
    where TExternalEntity : class, OTIS.Domain.IEntity, IFinancials, IExternalMapper<TExternalEntity, TQuickbooksEntity>, new()
    where TQuickbooksEntity : class, Intuit.Ipp.Data.IEntity, new()
{
    return CreateUpdateQuickBooksEntity<TQuickbooksEntity>(
        entity.ToQuickBooksEntity(preferences),
        x => x.Id == entity.FinancialsId,
        entity.FinancialsId);
}

尝试接口

public interface IExternalMapper<TExternalEntity, TQuickbooksEntity>
    where TExternalEntity : class, OTIS.Domain.IEntity, new()
    where TQuickbooksEntity : class, Intuit.Ipp.Data.IEntity, new()
{
    static TQuickbooksEntity ToQuickBooksEntity<TExternalEntity>(this TExternalEntity externalEntity, CompanyPreferencesFinancialsSystemCommon preferences);
}

这会产生错误:

Extension method must be defined in a non-generic static class

这个

public static class VendorExtensions : IExternalMapper<OTIS.Domain.InventoryMgmt.Vendor, Intuit.Ipp.Data.Vendor>
    {
        public static Intuit.Ipp.Data.Vendor ToQuickbooksEntity(this OTIS.Domain.InventoryMgmt.Vendor importedVendor)

Static classes cannot implement interfaces中的结果。

我理解为什么这不起作用。但是不知道如何重新构建代码以支持在泛型方法中使用扩展方法的要求。

3 个答案:

答案 0 :(得分:3)

他们几乎总结了

  

扩展方法必须在非泛型静态类中定义

只需在静态类

中定义扩展方法即可
public static class MapperExtensions    
{
     public static TQuickbooksEntity ToQuickBooksEntity<TExternalEntity>(this TExternalEntity externalEntity, CompanyPreferencesFinancialsSystemCommon preferences) 
                        where TExternalEntity : class, OTIS.Domain.IEntity, new()
                        where TQuickbooksEntity : class, Intuit.Ipp.Data.IEntity, new()
     {    
          //return do implimentation    
     }
}

然后当你想要映射它时,摆脱界面并直接使用扩展名。

using namespacetoextensions;

public ActionConfirmation<string> CreateUpdateEntity<TExternalEntity, TQuickbooksEntity>(TExternalEntity entity, CompanyPreferencesFinancialsSystemCommon preferences)
    where TExternalEntity : class, OTIS.Domain.IEntity, IFinancials, new()
    where TQuickbooksEntity : class, Intuit.Ipp.Data.IEntity, new()
{
    return CreateUpdateQuickBooksEntity<TQuickbooksEntity>(
        entity.ToQuickBooksEntity(preferences),
        x => x.Id == entity.FinancialsId,
        entity.FinancialsId);
}

为了澄清一下,您试图以一种他们根本无法工作的方式使用C#功能。

  

静态类是密封的,因此无法继承。他们   不能从除Object之外的任何类继承。

这意味着使用扩展方法实现接口很简单,无法正常工作。

所以你有两个选择,要么删除界面,要么直接使用扩展方法,如下所示:

public static class Extensions
{
    public static TExternalEntity ToQuickBooksEntity<TExternalEntity, TQuickbooksEntity>(this TQuickbooksEntity externalEntity)
        where TExternalEntity : class, OTIS.Domain.IEntity, new()
        where TQuickbooksEntity : class, Intuit.Ipp.Data.IEntity, new()
    {
        throw new NotImplementedException();
    }
}

或者您不能使用扩展方法,而是使用带有实现的接口。 (我会很明显地展示这个例子。)

答案 1 :(得分:1)

如果ToQuickBooksEntity的实现细节对于不同类型的TExternalEntity有显着差异,那么它可能不应该是扩展方法。它应该是适当类的实例方法,以便您可以利用多态性。

如果实现细节不太依赖于TExternalEntity的类型,并且您希望将其保留为扩展方法,那么就没有理由在接口上定义它。相反,将它作为静态类的方法。您需要的任何泛型类型约束都可以是方法本身的泛型约束,您不需要该类是通用的。

答案 2 :(得分:0)

  

扩展方法必须在非泛型静态类中定义

错误不清楚吗?扩展方法应该是一个静态方法,应该在非泛型静态类中定义才能工作。静态类也必须从System.Object继承,并且也不能实现任何interface

interface实现在静态类中是非法的,因为静态类不能有实例成员,但是没有实例成员,接口就没有意义。