Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在实体框架中传递字符串作为泛型数据库集的类型参数?_C#_Entity Framework_Reflection - Fatal编程技术网

C# 如何在实体框架中传递字符串作为泛型数据库集的类型参数?

C# 如何在实体框架中传递字符串作为泛型数据库集的类型参数?,c#,entity-framework,reflection,C#,Entity Framework,Reflection,考虑下面的示例代码,将C#泛型类型作为参数传递的最简洁方法是什么 public dynamic MyDbSet(string typeName) { var typeofDbSet = typeof(DbSet<>); Type[] typeArgs = { Type.GetType(typeName) }; var type = typeofDbSet.MakeGenericType(typeArgs); dynamic dbsetOfT = Act

考虑下面的示例代码,将C#泛型类型作为参数传递的最简洁方法是什么

public dynamic MyDbSet(string typeName)
{
    var typeofDbSet = typeof(DbSet<>);
    Type[] typeArgs = { Type.GetType(typeName) };
    var type = typeofDbSet.MakeGenericType(typeArgs);
    dynamic dbsetOfT = Activator.CreateInstance(type);

    return dbsetOfT;

    //Call it
    //var notificationTypes = MyDbSet("NotificationType");
    //var list = notificationTypes.ToList();
}
公共动态MyDbSet(字符串类型名)
{
var typeofDbSet=typeof(DbSet);
Type[]typeArgs={Type.GetType(typeName)};
var type=typeofDbSet.MakeGenericType(typeArgs);
动态dbsetOfT=Activator.CreateInstance(类型);
返回dbsetOfT;
//叫它
//var notificationTypes=MyDbSet(“NotificationType”);
//var list=notificationTypes.ToList();
}
或者像这样:

public dynamic MyDbSet2(string typeName)
{
    var keyValuePairs = new Dictionary<string, dynamic>
    {
        {nameof(NotificationType), Set<NotificationType>().AsQueryable()}
    };

    return keyValuePairs[typeName];
    //Call it
    //var notificationTypes = MyDbSet2("NotificationType");
    //var list = notificationTypes.ToList();
}
public DbSet<T> MyDbSet<T>() where T : class
{
    return (DbSet<T>)typeof(DbSet<T>).GetConstructor(BindingFlags.NonPublic |
       BindingFlags.Instance, null, Type.EmptyTypes, null).Invoke(null);
}
公共动态MyDbSet2(字符串类型名)
{
var keyValuePairs=新字典
{
{nameof(NotificationType),Set().AsQueryable()}
};
返回keyValuePairs[typeName];
//叫它
//var NotificationType=MyDbSet2(“NotificationType”);
//var list=notificationTypes.ToList();
}

Activator.CreateInstance(type)
将失败,因为
DbSet
没有公共的无参数构造函数。
除非您确实需要将类型名作为字符串传递,否则最好的方法是创建一个泛型函数,获取构造函数并调用它。它是这样的:

public dynamic MyDbSet2(string typeName)
{
    var keyValuePairs = new Dictionary<string, dynamic>
    {
        {nameof(NotificationType), Set<NotificationType>().AsQueryable()}
    };

    return keyValuePairs[typeName];
    //Call it
    //var notificationTypes = MyDbSet2("NotificationType");
    //var list = notificationTypes.ToList();
}
public DbSet<T> MyDbSet<T>() where T : class
{
    return (DbSet<T>)typeof(DbSet<T>).GetConstructor(BindingFlags.NonPublic |
       BindingFlags.Instance, null, Type.EmptyTypes, null).Invoke(null);
}
public DbSet MyDbSet(),其中T:class
{
return(DbSet)typeof(DbSet).GetConstructor(BindingFlags.NonPublic|
BindingFlags.Instance,null,Type.EmptyTypes,null).Invoke(null);
}
然后,您可以通过
MyDbSet()调用它

更新:
由于需要传递名称,因此可以执行以下操作:

public dynamic MyDbSet(string typeName)
{
    return typeof(DbSet<>).MakeGenericType(Type.GetType(typeName)).
        GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
        null, Type.EmptyTypes, null).Invoke(null);
}
公共动态MyDbSet(字符串类型名)
{
返回typeof(DbSet).MakeGenericType(Type.GetType(typeName))。
GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
null,Type.EmptyTypes,null).Invoke(null);
}

然后,您可以通过
MyDbSet(“.NotificationType”)
调用它。指定命名空间是必需的,否则
Type.GetType
将找不到该类型并返回
null

请尝试以下扩展代码:

//Use var list = _context.MyDbSet("ConsoleAppEF.Student").ToList();
public static IQueryable MySet(this SchoolContext context, string typeName)
{
    var T = Type.GetType(typeName);
    // Get the generic type definition
    MethodInfo method = typeof(SchoolContext)
        .GetMethod("MySet", BindingFlags.Public | BindingFlags.Instance);

    // Build a method with the specific type argument you're interested in
    method = method.MakeGenericMethod(T);

    return method.Invoke(context, null) as IQueryable;
}

public static IQueryable<T> Set<T>(this SchoolContext context)
{
    // Get the generic type definition 
    MethodInfo method = typeof(SchoolContext)
        .GetMethod(nameof(SchoolContext.Set), BindingFlags.Public | BindingFlags.Instance);

    // Build a method with the specific type argument you're interested in 
    method = method.MakeGenericMethod(typeof(T));

    return method.Invoke(context, null) as IQueryable<T>;
}

public static IList ToList1(this IQueryable query)
{
    var genericToList = typeof(Enumerable).GetMethod("ToList")
        .MakeGenericMethod(new Type[] { query.ElementType });
    return (IList)genericToList.Invoke(null, new[] { query });
}
使用它:

class Program
{
    static void Main(string[] args)
    {
        Seed();
        var _context = new SchoolContext();
        var list = _context.MySet("ConsoleAppEF.Student").ToList1();
    }

    private static void Seed()
    {
        var _context = new SchoolContext();
        var students = new List<Student>
        {
            new Student{FirstMidName="Carson",LastName="Alexander"},
        };

        students.ForEach(s => _context.Students.Add(s));
        _context.SaveChanges();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
种子();
var_context=新学校上下文();
var list=_context.MySet(“ConsoleAppEF.Student”).ToList1();
}
私有静态void Seed()
{
var_context=新学校上下文();
var students=新列表
{
新学生{FirstMidName=“Carson”,LastName=“Alexander”},
};
students.ForEach(s=>_context.students.Add(s));
_SaveChanges();
}
}

我没有,NotificationType,我只有NotificationType字符串_context.MyDbSet(“ConsoleAppEF.Student”).ToList()“”System.Data.Entity.DbSet'不包含“ToList”的定义,但如何使用Linq对Iquerable进行过滤?MySet只返回不能与linq语句一起使用的非泛型Iqueriable。