C# 如何从使用DynamicMethod和实体框架的代码中提取类型参数?

C# 如何从使用DynamicMethod和实体框架的代码中提取类型参数?,c#,entity-framework,reflection,dynamicmethod,dynamic-method,C#,Entity Framework,Reflection,Dynamicmethod,Dynamic Method,我正在创建一个框架,该框架旨在允许web开发人员创建CRUD页面,而无需执行重复步骤 为此,我希望提供“默认”方法,这些方法可以执行排序、筛选等操作。如果愿意,使用我的框架的开发人员可以提供自己的方法,但在许多情况下应该有一个默认方法 对我来说,与实体框架兼容尤其重要 我已经使用DynamicMethod类成功地实现了一个默认过滤函数,该类允许通过搜索键对实体框架生成的任意类进行“通用”过滤 我试图做一些类似的排序,但我遇到了一个问题。方法采用两个类型参数,第一个是实体类型,第二个是“键”类型。

我正在创建一个框架,该框架旨在允许web开发人员创建CRUD页面,而无需执行重复步骤

为此,我希望提供“默认”方法,这些方法可以执行排序、筛选等操作。如果愿意,使用我的框架的开发人员可以提供自己的方法,但在许多情况下应该有一个默认方法

对我来说,与实体框架兼容尤其重要

我已经使用
DynamicMethod
类成功地实现了一个默认过滤函数,该类允许通过搜索键对实体框架生成的任意类进行“通用”过滤

我试图做一些类似的排序,但我遇到了一个问题。方法采用两个类型参数,第一个是实体类型,第二个是“键”类型。该键类型需要与用户想要排序的列的类型匹配,为了使其与所有实体类一起工作,需要在运行时确定类型

我已经使用反射来发现列的类型,但我不知道如何将“comparer”函数强制转换为适当的Func类型。因此,我设置了一个switch语句来打开类型。我想去掉switch语句并计算出密钥类型

我该怎么做?我的代码如下:

    public override IEnumerable<T> GetSortedRecords<T>(IEnumerable<T> filteredRecords) 
    {
        // The goal here is to allow for a developer to provide a method for sorting records,
        // but to also provide a default method that will work with all instances of EntityObject.
        // To that end, I believe it is necessary to use the fun fun DynamicMethod object.

        // Note - check for ASC vs DESC

        if (NumberOfSorts == 0)
            return filteredRecords;

        IOrderedEnumerable<T> sortedRecords = null;
        for (int i = 0; i < NumberOfSorts; i++)
        {
            string propertyName = PropertyNames[ColumnSortOrder[i]];
            PropertyInfo property = typeof(T).GetProperties().Single(p => p.Name == propertyName);                                                                

            switch (property.PropertyType.Name)
            {
                // I want to get rid of these branches.
                case "Int32":
                    Func<T, int> comparerInt32 = GetDefaultKeySelectorForProperty<T, Int32>(property);
                    sortedRecords = i == 0 ?
                    filteredRecords.OrderBy<T, int>(comparerInt32) :
                    sortedRecords.ThenBy<T, int>(comparerInt32);
                    break;
                case "String":
                    Func<T, string> comparerString = GetDefaultKeySelectorForProperty<T, string>(property);
                    sortedRecords = i == 0 ?
                    filteredRecords.OrderBy<T, string>(comparerString) :
                    sortedRecords.ThenBy<T, string>(comparerString);
                    break;
                default:
                    throw new NotImplementedException();
            }                                    
        }
        return sortedRecords;                        
    }

    delegate TKey GetDefaultKeySelectorForPropertyDelegate<T, TKey>(T t);
    public Func<T, TKey> GetDefaultKeySelectorForProperty<T, TKey>(PropertyInfo property)
    {
        DynamicMethod method = new DynamicMethod("GetKeySelector", typeof(TKey), new Type[] { typeof(T) });
        ILGenerator generator = method.GetILGenerator();

        MethodInfo GetPropertyValue = property.GetGetMethod();
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Callvirt, GetPropertyValue);
        generator.Emit(OpCodes.Ret);

        return ((GetDefaultKeySelectorForPropertyDelegate<T, TKey>)(method.CreateDelegate(typeof(GetDefaultKeySelectorForPropertyDelegate<T, TKey>)))).Invoke;
    }
公共覆盖IEnumerable GetSortedRecords(IEnumerable filteredRecords)
{
//这里的目标是允许开发人员提供一种排序记录的方法,
//但也要提供一个默认方法,该方法将处理EntityObject的所有实例。
//为此,我认为有必要使用fun DynamicMethod对象。
//注-检查ASC与DESC
如果(NumberOfSorts==0)
返回过滤器记录;
IOrderedEnumerable sortedRecords=null;
for(int i=0;ip.Name==propertyName);
开关(property.PropertyType.Name)
{
//我想除掉这些树枝。
案例“Int32”:
Func comparerInt32=GetDefaultKeySelectorForProperty(属性);
sortedRecords=i==0?
filteredRecords.OrderBy(比较器32):
分类记录。然后通过(比较32);
打破
大小写“字符串”:
Func comparerString=GetDefaultKeySelectorForProperty(属性);
sortedRecords=i==0?
filteredRecords.OrderBy(比较器字符串):
分类记录。然后按(比较器串);
打破
违约:
抛出新的NotImplementedException();
}                                    
}
返回分拣记录;
}
委托TKey GetDefaultKeySelectorForPropertyLegate(T);
公共函数GetDefaultKeySelectorForProperty(PropertyInfo属性)
{
DynamicMethod=newdynamicmethod(“GetKeySelector”,typeof(TKey),newtype[]{typeof(T)});
ILGenerator=method.GetILGenerator();
MethodInfo GetPropertyValue=property.GetMethod();
生成器.Emit(操作码.Ldarg_0);
Emit(opcode.Callvirt,GetPropertyValue);
生成器.Emit(操作码.Ret);
return((GetDefaultKeySelectorForPropertyDelegate)(method.CreateDelegate(typeof(GetDefaultKeySelectorForPropertyDelegate))).Invoke;
}

如果要执行真正的动态调用,调用站点也处理运行时字段,那么LINQ中有两种基本的动态表达式和查询方法

a) 字符串动态Lambda

System.Linq.Dynamic可在以下链接中找到

b) 构建表达式树

更强大但更难掌握。。。使用以下代码生成表达式树:

但是,如果您只需要Resposityory模式generic,并且调用站点将知道可以提供谓词,那么类似这样的内容

    /// <summary>
    /// The sorted page list is the main way of retrieving a subset of data.  
    /// </summary>
    /// <typeparam name="TSortKey"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="sortBy"></param>
    /// <param name="descending"></param>
    /// <param name="skipRecords"></param>
    /// <param name="takeRecords"></param>
    /// <returns></returns>
    public virtual IQueryable<TPoco> GetSortedPageList<TSortKey>(Expression<Func<TPoco, bool>> predicate,
                                     Expression<Func<TPoco, TSortKey>> sortBy, bool descending, int skipRecords, int takeRecords) {
        if (!descending) {
            return Context.Set<TPoco>().Where<TPoco>(predicate)
                     .OrderBy(sortBy)
                    .Skip(skipRecords)
                    .Take(takeRecords);
        }
        return
            Context.Set<TPoco>().Where<TPoco>(predicate)
                .OrderByDescending(sortBy)
                .Skip(skipRecords)
                .Take(takeRecords);
    }
//
///排序页面列表是检索数据子集的主要方式。
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 
公共虚拟IQueryable GetSortedPageList(表达式谓词,
表达式排序、bool降序、int skipRecords、int takeRecords){
如果(!下降){
返回Context.Set().Where(谓词)
.OrderBy(sortBy)
.Skip(skipRecords)
.Take(takeRecords);
}
返回
Context.Set().Where(谓词)
.OrderByDescending(排序方式)
.Skip(skipRecords)
.Take(takeRecords);
}
抽样电话

[TestMethod]
    public void BaseRepositoryPagingTest() {
        var luw = new LuwMaster();

        var someMore = true;
        var skip = 0;
        var take = 3;

        while (someMore) {
            var mimeList = luw.GetRepository<MimeType>().GetSortedPageList(m => true, m => m.Id, true, skip, take);
            someMore = false;
            foreach (var mimeType in mimeList) {
                Debug.WriteLine( mimeType.MimeTypeCategory + ", " + mimeType.Id);
                someMore = true;
            }
            skip = skip + take;
        }
    }
[TestMethod]
public void BaseRepositoryPagingTest(){
var luw=新的LuwMaster();
var someMore=真;
var-skip=0;
var=3;
而(更多){
var mimeList=luw.GetRepository().GetSortedPageList(m=>true,m=>m.Id,true,skip,take);
someMore=假;
foreach(mimeList中的var mimeType){
Debug.WriteLine(mimeType.mimetypecegory+“,”+mimeType.Id);
someMore=正确;
}
跳过=跳过+接受;
}
}
您可能会喜欢。