使用从GetType()派生的类型而不使用Switch

时间:2017-11-13 21:21:54

标签: c# entity-framework linq gridview reusability

我正在使用Entity Framework和LINQ。我想在GridViews的“帮助器”类中创建一个可重用的方法。

该方法将根据传递的实体类型将DataSource作为实体列表返回。

因此GridView1将显示[Entity1],因此调用将如下所示:

GridView1.DataSource = helperClass.GetDataSource(new Entity1());

注意*如果我应该在方法中传递我想要的实体类型作为字符串,我会打开提示。我只是不想在这个方法可以返回的~40个实体类型之间使用切换案例

可重用的方法很简单,看起来类似于:

public static object GetDataSource(object type)
{
    using (DatabaseContext dc = new DatabaseContext())
    {
        if (dc.[how do I get the entity type here].Count() > 0)
        {
            var modelList = dc.[how do I get the entity type here also].ToList();
        }
    }
}

这听起来很傻,但显然我无法做到:

var modelList = dc.(type.GetType()).ToList();

但这基本上就是我想要完成的事情。

2 个答案:

答案 0 :(得分:0)

如果要在编译时绑定类型,可以将类型作为泛型参数传递,并使用以下类型的方法:

        public DbSet<T> GetDataSource<T>()
        {
            var targetType = typeof(DbSet<T>);

            return _db
                .GetType()
                .GetMethods()
                .Where( m => m.ReturnType == targetType)
                .Single()
                .Invoke(_db, null) as DbSet<T>;
        }

它是如何工作的?好吧,我们不知道返回正在请求的实体的方法的名称,但我们知道返回类型必须是DbSet<T>。因此,我们扫描DatabaseContext以获取返回该类型的任何方法,并调用它。这假设只有一种方法具有该返回类型。

如果您需要真正的运行时绑定(您无法提供<T>参数),则可以使用此类方法。请注意,返回类型只是一般IEnumerable,因为如果在编译时未知,则无法使用特定的返回类型。如果需要,您可以随时将其强制转换为DbSet<T>

        public IEnumerable GetDataSource(Type type)
        {
            var targetType = typeof(DbSet<>).MakeGenericType(new Type[] { type });

            return _db
                .GetType()
                .GetMethods()
                .Where( m => m.ReturnType == targetType)
                .Single()
                .Invoke(_db, null) as IEnumerable;
        }

这是一个完整的例子。请注意,我删除了EF对象,但此示例仍应使用真实的DbSetDatabaseContext

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

public class Program
{

    public class DbSet<T> : List<T>
    {
    }

    public class User
    {
        public string Name { get; set; }
        public override string ToString()
        {
            return "User " + Name;
        }
    }

    public class Transaction
    {
        public decimal Amount { get; set; }
        public override string ToString()
        {
            return "Transaction " + Amount.ToString("0.00");
        }
    }

    public class DatabaseContext
    {
        public DbSet<User> GetUsers() 
        {
            return new DbSet<User>()
            {
                new User { Name = "Bob" },
                new User { Name = "Alice" }
            };
        }
        public DbSet<Transaction> GetTransactions() 
        {
            return new DbSet<Transaction>()
            {
                new Transaction { Amount = 12.34M },
                new Transaction { Amount = 56.78M }
            };
        }

    }

    public class HelperClass
    {
        private readonly DatabaseContext _db;

        public HelperClass(DatabaseContext db)
        {
            _db = db;
        }

        public DbSet<T> GetDataSource<T>()
        {
            var targetType = typeof(DbSet<T>);

            return _db
                .GetType()
                .GetMethods()
                .Where( m => m.ReturnType == targetType)
                .Single()
                .Invoke(_db, null) as DbSet<T>;
        }

        public IEnumerable GetDataSource(Type type)
        {
            var targetType = typeof(DbSet<>).MakeGenericType(new Type[] { type });

            return _db
                .GetType()
                .GetMethods()
                .Where( m => m.ReturnType == targetType)
                .Single()
                .Invoke(_db, null) as IEnumerable;
        }
    }

    public static void Main()
    {
        var helperClass = new HelperClass(new DatabaseContext());

        foreach (var u in helperClass.GetDataSource<User>())
        {
            Console.WriteLine(u);
        }

        foreach (var t in helperClass.GetDataSource(typeof(Transaction)))
        {
            Console.WriteLine(t);
        }

    }
}

输出:

User Bob
User Alice
Transaction 12.34
Transaction 56.78

Full code on DotNetFiddle

答案 1 :(得分:0)

这种方法不合理,我最终将GridView的数据源存储在SessionState变量中。节省了每次回发都需要重新查询DataSource的麻烦(如果我在重新查询时必须跟踪订单号,可能会变得很乏味。相反,sessionstate变量会保持排序顺序)