自定义扩展方法与框架扩展方法冲突。为什么?

时间:2009-12-29 21:40:52

标签: c# datatable extension-methods

我的申请表中有一个奇怪的行为。我想迭代表的行(DataTable)。我想使用AsEnumerable()类中的DataTableExtensions扩展方法。 Sonmething喜欢:

foreach(var thing in table.AsEnumerable())
{
...
}

编译时,它抱怨我需要引用一些ESRI DLL(GIS应用程序)。经过一番挖掘后,我从引用的DLL中找到了一些扩展方法,这些扩展方法扩展了ESRI中的一些类型(例如IEnumFieldIEnumLayer等)。

显然,DataTable与那些不同,我似乎无法找到为什么它试图绑定到AsEnumerable(this IEnumLayer)而不是AsEnumerable(this DataTable)。有趣的是我们正在使用 Resharper (非常棒的工具!)和Resharper在我们这边:当您导航到定义时,它会将您带到对象浏览器中的AsEnumerable(this DataTable)

我不能在这里发布很多代码示例而不发布数千行专有代码所以我只是在寻找一个我曾经遇到过同样的问题而且我修复了它... 类型答案。

显而易见的解决方案是通过删除该命名空间的所有using语句来删除对扩展方法的任何引用。但这会产生令人讨厌的副作用,迫使我们完全限定任何类型的声明。不漂亮。

提前感谢任何输入。

埃里克。

5 个答案:

答案 0 :(得分:0)

您可以使用using [alias = ]class_or_namespace;的alias =部分。然后你会得到类似using my = System.Data;的内容,然后将其与my.DataTable.AsEnumerable();

一起使用

答案 1 :(得分:0)

foreach(var thing in ((DataTable)table).AsEnumerable())
{
...
}

试试....

答案 2 :(得分:0)

我不确定你为什么会遇到这个问题,但是一个潜在的解决方法是放弃扩展方法语法糖,只需将AsEnumerable视为常规静态方法:

foreach (var thing in DataTableExtensions.AsEnumerable(table))
{
    // do something
}

答案 3 :(得分:0)

你可以发布你的班级层次结构吗?

以下代码显示选择了派生时最多的编译时类型扩展方法。 它适用于您的代码吗?

    [TestMethod]
    public void Test1()
    {
        IEnumerable<MyCustomClass> myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Ignores MyCustomList method and uses IEnumerable<> method.
        Assert.AreEqual(2, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test2()
    {
        MyCustomList myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Uses MyCustomList method
        Assert.AreEqual(1, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test3()
    {
        ISomeInterface myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //If your type is ISomeInterface, the compiler uses ISomeInterface method, even if the runtime instance is MyCustomList
        Assert.AreEqual(0, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test4()
    {
        MyDerivedCustomList myCustomList = new MyDerivedCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Even if MyDerivedCustomList implements ISomeInterface, the compiler uses MyCustomList method
        Assert.AreEqual(1, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test5()
    {
        ISomeInterface myCustomList = new MyDerivedCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //If your type is ISomeInterface, the compiler uses ISomeInterface method, even if the runtime instance is MyDerivedCustomList
        Assert.AreEqual(0, myCustomList.Where(x => x.Int1 > 1).Count());
    }

使用此类:

public class MyCustomClass
{
    public int Int1 { get; set; }
}

public class MyCustomList : List<MyCustomClass>, ISomeInterface
{
    public MyCustomList() : base() { }
    public MyCustomList(IEnumerable<MyCustomClass> coll) : base(coll) { }
}

public interface ISomeInterface : IEnumerable<MyCustomClass>
{
}

public class MyDerivedCustomList : MyCustomList, ISomeInterface
{
    public MyDerivedCustomList() : base() { }
    public MyDerivedCustomList(IEnumerable<MyCustomClass> coll) : base(coll) { }
}

public static class MyExtensions
{
    /// <summary>
    /// Where(x => x.Int1 > 2)
    /// </summary>
    public static IEnumerable<MyCustomClass> Where(this MyCustomList myList, Func<MyCustomClass, bool> predicate)
    {
        return new MyCustomList(Enumerable.Where(myList, predicate).Where(x => x.Int1 > 2));
    }

    /// <summary>
    /// Where(x => x.Int1 > 3)
    /// </summary>
    public static IEnumerable<MyCustomClass> Where(this ISomeInterface myList, Func<MyCustomClass, bool> predicate)
    {
        return new MyCustomList(Enumerable.Where(myList, predicate).Where(x => x.Int1 > 3));
    }
}

答案 4 :(得分:0)

也许以下方法效果最好:

foreach (DataRow dr in table.Rows)
{
}