c#如何从List<T>对象作为参数传递

  • 本文关键字:对象 参数传递 List c#
  • 更新时间 :
  • 英文 :


我需要从我的函数Selectus返回一行列表。

传递给函数Selectus对象反映数据库表字段我需要返回一行匹配参数looking_for:

public static List<T> Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine

db.Dispose();

//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object

var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.ToList();//here one record should be returned
}

假设T参数变化,我不知道如何从列表中选择一行。在SelectusT>方法,我想传递不同的对象,反映数据库表中的字段,而不是为每个选择创建单独的方法。例如,调用Selectus,其中传递的对象是公共类ProductCodes{公共int ID {get;设置;}公共字符串SapIndex {get;设置;}公共字符串SapName {get;设置;}}。然后我想为另一张表调用另一个Selectus<ProductTypes>等等……所以我想写通用/整体的方法,并使用它普遍为所有类型的我的对象,反映了几个数据库表的字段。SapIndex属性总是在所有对象的相同位置…

使用prop[1]非常脆弱。谁说你现在感兴趣的房产总是排在第二位?如果明天有人又添了一处房产怎么办?如果不是你使用的每个T在属性列表的第二位都有相同的属性怎么办?你在这里的实际目标是什么,以及你为什么采取反思路线,这是相当不清楚的。

您最好在这里使用继承或接口实现。在这个答案中,我将使用接口,但两者都可以。

为了清楚起见,让我们假设在所有可能的列表中都有一个Code字段,并且这是您试图匹配的属性。

  1. 定义一个可重用的接口:
public interface ICodeEntity
{
string Code { get; }
}
  1. 将你的接口应用到你打算用于Selectus方法的所有类
public class Person : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
public class Document : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
  1. 添加一个泛型类型约束,限制T仅用于实现您的接口的类型。
public static List<T> Selectus<T>(string code)
where T : ICodeEntity
  1. 你现在可以用一种方式来编写你的代码,它依赖于有Code属性的类型,编译器将帮助执行它。
var db = OrmLiteBaza().Open();
var list = db.Select<T>().ToList();            
db.Dispose();
return list.Where(item => item.Code == code).ToList();
  1. 使用示例:
List<Person> peopleWithCodeABC = Selectus<Person>("ABC");
List<Person> documentsWithCodeXYZ = Selectus<Document>("XYZ");
// This will fail if Animal does not implement ICodeEntity
var compilerError = Selectus<Animal>("ABC");

我可能不完全理解你想要什么,但代替string looking_for,你可以传递一个Func<,>委托,作为一个选择器。

类似:

public static List<TField> Selectus<T, TField>(Func<T, TField> selector)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();

db.Dispose();

var list_selected_record = select_all_list.Select(selector);  // 'using System.Linq;'        
return list_selected_record.ToList();
}

那么我认为它可以这样命名:

var list_one = Selectus((ProductCodes x) => x.SapIndex);
var list_two = Selectus((ProductTypes x) => x.SapIndex);
var list_three = Selectus((ProductCodes x) => x.SapName);

在这种语法中,我省略了方法的<ProductCodes, string>泛型参数,因为它们可以被推断出来。


嗯,也许你想在相反的维度。你可以这样做:

public static List<T> Selectus<T>(Func<T, bool> predicate)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();

db.Dispose();

var list_selected_record = select_all_list.Where(predicate);  // 'using System.Linq;'        
return list_selected_record.ToList();
}

:

var list_one = Selectus((ProductCodes x) => x.SapIndex == "ABC");
var list_two = Selectus((ProductTypes x) => x.SapIndex == "ABC");
var list_three = Selectus((ProductCodes x) => x.SapName == "DaName");

或:

var list_one = Selectus<ProductCodes>(x => x.SapIndex == "ABC");
var list_two = Selectus<ProductTypes>(x => x.SapIndex == "ABC");
var list_three = Selectus<ProductCodes>(x => x.SapName == "DaName");

但是如果它总是"相同"属性,就像x.SapIndex一样(但对于不同类型的x),那么Flater的答案看起来不错。

否则,如果你坚持,你的反射方法应该是可能的。使用属性的名称,而不是它的索引!让我试试:

public static List<T> Selectus<T>(string looking_for)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();

db.Dispose();

const string prop_name = "SapIndex";
var prop = typeof(T).GetProperty(prop_name);  // can blow up for bad T
var list_selected_record = select_all_list
.Where(x => (string)(prop.GetValue(x)) == looking_for);  // 'using System.Linq;'        
return list_selected_record.ToList();
}

:

var list_one = Selectus<ProductCodes>("ABC");
var list_two = Selectus<ProductTypes>("ABC");

您可以更改代码以只返回一个元素

public static T Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine

db.Dispose();

//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object

var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.FirstOrDefault();//here one record should be returned
}

最新更新