繁体   English   中英

C#如何从列表中返回1行<T>作为参数传递的对象

[英]C# how to return 1 row from List<T> object passed as parameter

我需要从我的函数 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> 方法中,我想将反映数据库表中字段的不同对象作为 T 传递,而不是为每个选择创建单独的方法。 例如调用 Selectus,其中传递的对象是 public class ProductCodes { public int ID { get; 放; } 公共字符串 SapIndex { 获取; 放; } 公共字符串 SapName { 获取; 放; } }。 然后我想为另一个表调用另一个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");

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

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
}

我可能不完全理解您想要的内容,但是您可以通过func Func<,>代表的委托,而不是string looking_for

就像是:

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");

如何从列表转换<object>列出<t>在 c# 中?<div id="text_translate"><p> 我有一个 Class:</p><pre> public class Element { public List&lt;object&gt; objects { get; set; } }</pre><p> 还有一个 Class:</p><pre> public class Node { public long id { get; set; } }</pre><p> 我传入一个List&lt;object&gt; nodes 。 那么有什么方法可以将这些List&lt;object&gt; objects转换为List&lt;Node&gt; nodes ?</p><p> 我试过这种方式,但它不起作用List&lt;Node&gt; nodes = objects.Select(s =&gt; (nodes)s).ToList();</p></div></t></object>

[英]How to convert from List<object> to List<T> in c#?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM