2

我对 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;
    }
}

错误信息是

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

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

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

4

2 回答 2

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;
    }
}

另一种解决方案是执行以下操作:

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;
    }
}

现在,你可以让它更干净,因为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;
    }
}

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

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)];
    }
}
于 2012-10-18T17:08:23.817 回答
1

我建议(除了阅读泛型和一般的 C# 之外)在运行时使用所需的类型配置池,将它们存储在字典中并使用Typeas 键,即类似于以下几行的内容......:

//...

// configuration, maybe factor out to a dedicated class...
private readonly IDictionary<System.Type, IQueryable> m_SupportedPools =
    new Dictionary<System.Type, IQueryable>();

// add this queryable, note that type inference works here
public void AddToPool<T>(IQueryable<T> p_Queryable)
{
    m_SupportedPools.Add(typeof(T), p_Queryable);
}

public IQueryable<T> GetPool<T>()
{
    IQueryable t_Set = null;  
    if (m_SupportedQueries.TryGetValue(typeof(T), out t_Set)) {
        return t_Set as IQueryable<T>;
    } else {
        return null;
    }
}
于 2012-10-18T17:40:26.210 回答