简体   繁体   English

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

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

I need to return one row of List from my function Selectus.我需要从我的函数 Selectus 返回一行列表。

So I pass to the function Selectus object that reflects database table fields and I need to return one row which match the parameter looking_for:所以我传递给反映数据库表字段的函数 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
}

I do not know how to select one row from the list assuming that T parameter is vary.假设 T 参数不同,我不知道如何从列表中选择一行。 In SelectusT> method I want to pass as T different objects which reflect fields in database table rather than creatinig separate methods for each select.在 SelectusT> 方法中,我想将反映数据库表中字段的不同对象作为 T 传递,而不是为每个选择创建单独的方法。 eg call Selectus, where object passed is public class ProductCodes { public int ID { get;例如调用 Selectus,其中传递的对象是 public class ProductCodes { public int ID { get; set;放; } public string SapIndex { get; } 公共字符串 SapIndex { 获取; set;放; } public string SapName { get; } 公共字符串 SapName { 获取; set;放; } }. } }。 Then I want to call another Selectus<ProductTypes> for another table etc... So I want to write generic/overall method and use it universally for all types of my objects which reflects the fields of few database tables.然后我想为另一个表调用另一个Selectus<ProductTypes>等等......所以我想编写通用/整体方法并将其普遍用于我的所有类型的对象,这反映了几个数据库表的字段。 The SapIndex property is always in the same place of all objects... SapIndex 属性始终位于所有对象的相同位置...

Using prop[1] is incredibly fragile.使用prop[1]非常脆弱。 Who says that the property you're currently interested in is always going to be in second place?谁说你目前感兴趣的房产总是排在第二位? What if someone adds another property tomorrow?如果有人明天添加另一个属性怎么办? What if not every T that you use have the same property in the second place on its list of properties?如果不是您使用的每个 T 在其属性列表中的第二位都具有相同的属性怎么办? It is quite unclear what your actual goal is here and why you've taken the reflection route.目前还不清楚你的实际目标是什么,以及你为什么要采取反思路线。

You would be better off using inheritance or interface implementation here.你最好在这里使用继承或接口实现。 I'm going to use an interface in this answer, but either would work.我将在这个答案中使用一个界面,但任何一个都可以。

For the sake of clarity, let's assume there is a Code field in all your possible lists, and this is the property you're trying to match with.为了清楚起见,我们假设在所有可能的列表中都有一个Code字段,这是您尝试匹配的属性。

  1. Define a reusable interface:定义一个可重用的接口:
public interface ICodeEntity
{
    string Code { get; }
}
  1. Apply your interface to all of the classes that you intend to use for your Selectus method.将您的接口应用于您打算用于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. Add a generic type constraint that limits the use of T only to types that implement your interface.添加一个泛型类型约束,将T的使用限制为仅用于实现您的接口的类型。
public static List<T> Selectus<T>(string code)
    where T : ICodeEntity
  1. You can now write your code in a way that it relies on the type in question having a Code property, and the compiler will help enforce it.您现在可以以依赖于具有Code属性的相关类型的方式编写代码,并且编译器将帮助执行它。
var db = OrmLiteBaza().Open();
var list = db.Select<T>().ToList();            
db.Dispose();

return list.Where(item => item.Code == code).ToList();
  1. Usage examples:使用示例:
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");

you can change code to return just one element您可以更改代码以仅返回一个元素

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
}

I might not understand fully what you want, but instead of string looking_for you could pass in a Func<,> delegate which acts as a selector.我可能不完全理解您想要的内容,但是您可以通过func Func<,>代表的委托,而不是string looking_for

Something like:就像是:

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();
}

Then I believe it could be called like this:然后我相信它可以这样称呼:

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

With this syntax I leave out the <ProductCodes, string> generic arguments to the method since they can be inferred.使用这种语法,我省略了该方法的<ProductCodes, string>通用参数,因为它们可以被推断出来。


Hmm, maybe you want it in the opposite dimension.嗯,也许你想要它在相反的维度。 You could do:你可以这样做:

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();
}

with:和:

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

or:或者:

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

But if it is going to always be the "same" property, like always x.SapIndex (but for different types of x ), then Flater's answer looks good.但是,如果它始终是“相同”的属性,就像x.SapIndex一样(但对于不同类型的x ),那么 Flater 的答案看起来不错。

Otherwise, if you insist, your reflection approach should be possible.否则,如果你坚持,你的反思方法应该是可能的。 Use propety's name, not its index!使用属性的名称,而不是它的索引! Let me try:让我试试:

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();
}

with:和:

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.

相关问题 C#-如何基于传递给方法的参数返回泛型列表 - C# - How to return a Generic List based on a passed parameter to the Method C#从列表传递对象 <T> 作为参数 - C# passing Object from List<T> as parameter 如何从List中删除对象 <T> 在C#中返回被删除的对象? - How to remove an object from List<T> in C# and return the removed object? C# - 循环通过从新线程传递的对象参数 - C# - Looping through object parameter that was passed from new thread 如何从c#中的web api返回动态对象列表 - How to return a dynamic object list from web api in c# 如何在C#中返回已生成对象的通过属性的值 - How to return a value of passed in property of generated object in c# 如何从列表转换<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#? 退货清单 <object> 来自IEnumerable C# - Return List<object> from IEnumerable C# 如何使用列表C#返回对象 - How to return object using list c# 如何将wchar_t *从C ++编组为C#作为out参数或返回值? - How do I marshal wchar_t* from C++ to C# as an out parameter or return value?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM