C#:专用模板方法 - 错误:类型“...”已经定义了一个名为“...”的成员,具有相同的参数类型

SDw*_*rfs 2 c# templates entity-framework-4

我对 C# 很陌生,目前正在使用 EntityFramework 开发应用程序。我想扩展数据库上下文类的功能,以便我可以调用方法 getPool() 以便它分发该类的相应 DbSet 成员。

我需要将它实现为一个模板,因为它稍后会从其他模板中调用,这些模板只知道(全局)数据库上下文对象和类型 T(具有给定的超类),它们将查询数据库。

这是我尝试过的(有点简化 - 原始示例太复杂):

public class TestContext : DbContext
{
    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public IQueryable<T> getPool<T>() where T : TestA {
       return (IQueryable<T>)ATests;
    }
    public IQueryable<T> getPool<T>() where T : TestB {
       return (IQueryable<T>)BTests;
    }
}
Run Code Online (Sandbox Code Playgroud)

错误信息是

错误:类型“...”已经定义了一个名为“...”的成员,其参数类型相同

它出现在我的模板 ( public IQueryable<T> getPool<T>() where T : TestB)的第二个专门定义的行中。

问题是:如何解决这个问题?

And*_*are 5

不幸的是,在 C# 中,您不能通过使用像这样的泛型类型约束来重载方法。你将不得不给他们这样不同的名字

public class TestContext : DbContext
{
    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public IQueryable<T> getPoolA<T>() where T : TestA {
       return (IQueryable<T>)ATests;
    }
    public IQueryable<T> getPoolB<T>() where T : TestB {
       return (IQueryable<T>)BTests;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是做这样的事情:

public class TestContext : DbContext
{
    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public IQueryable<T> getPool<T>() {
       return (typeof(T) == typeof(TestA))
                  ? (IQueryable<T>)ATests
                  : (IQueryable<T>)BTests;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使这更清晰,因为在 中IQueryable<T>是协变的T,您可以避免强制转换:

public class TestContext : DbContext
{
    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public IQueryable<T> getPool<T>() {
       return (typeof(T) == typeof(TestA)) ? ATests : BTests;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想避免测试类型,您可以执行以下操作:

public class TestContext : DbContext
{
    readonly Dictionary<Type, object> _sets;

    public DbSet<TestA> ATests { get; set; }
    public DbSet<TestB> BTests { get; set; }

    public TestContext()
    {
        _sets = new Dictionary<Type, object>
        {
            { typeof(TestA), ATests },
            { typeof(TestB), BTests }
        }
    }

    public IQueryable<T> getPool<T>() {
       return (IQueryable<T>)_sets[typeof(T)];
    }
}
Run Code Online (Sandbox Code Playgroud)