从 List中获取一个元素基于ID
这个问题与这个问题相关: 给定 System.Type T,反序列化列表
给定此函数来检索所有元素的列表...
public static List<T> GetAllItems<T>()
{
XmlSerializer deSerializer = new XmlSerializer(typeof(List<T>));
TextReader tr = new StreamReader(GetPathBasedOnType(typeof(T)));
List<T> items = (List<T>)deSerializer.Deserialize(tr);
tr.Close();
}
...我想创建一个函数来仅检索具有所需 UID(唯一 ID)的元素中的一项:
public static System.Object GetItemByID(System.Type T, int UID)
{
IList mainList = GetAllItems<typeof(T)>();
System.Object item = null;
if (T == typeof(Article))
item = ((List<Article>)mainList).Find(
delegate(Article vr) { return vr.UID == UID; });
else if (T == typeof(User))
item = ((List<User>)mainList).Find(
delegate(User ur) { return ur.UID == UID; });
return item;
}
但是,这不起作用,因为 GetAllItems
调用格式不正确。
问题 1a:假设所有调用 GetItemByID() 的类都将 UID 作为其中的元素,如何修复第二个函数以正确返回唯一元素?我很乐意能够执行 public static
(如果可能)。
问题1b:同样的问题,但假设我无法修改GetItemByID的函数原型?
This question is related to this question: Given System.Type T, Deserialize List<T>
Given this function to retrieve a list of all elements...
public static List<T> GetAllItems<T>()
{
XmlSerializer deSerializer = new XmlSerializer(typeof(List<T>));
TextReader tr = new StreamReader(GetPathBasedOnType(typeof(T)));
List<T> items = (List<T>)deSerializer.Deserialize(tr);
tr.Close();
}
...I want to create a function to retrieve just one item of those with the needed UID (Unique ID):
public static System.Object GetItemByID(System.Type T, int UID)
{
IList mainList = GetAllItems<typeof(T)>();
System.Object item = null;
if (T == typeof(Article))
item = ((List<Article>)mainList).Find(
delegate(Article vr) { return vr.UID == UID; });
else if (T == typeof(User))
item = ((List<User>)mainList).Find(
delegate(User ur) { return ur.UID == UID; });
return item;
}
However, this does not work since GetAllItems<typeof(T)>();
call is not properly formed.
Question 1a: How can I fix the second function to properly return a unique element, given that all classes that will call GetItemByID() have UID as an element in them? I'd love to be able to do public static <T> GetItemByID<T>(int UID)
if possible.
Question 1b: Same question, but suppose I cannot modify the function prototype of GetItemByID?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
1a.确保所有 T 都实现定义属性
UID
的接口IUniqueIdentity
,然后限制泛型方法仅接受IUniqueIdentity
类型。所以:1a. Ensure that all T implement interface
IUniqueIdentity
which defines a propertyUID
then constrain a generic method to accept onlyIUniqueIdentity
types. So:将 GetItemByID 方法修改为通用方法:
public static T GetItemByID(int UID)
不起作用,正如您所指出的,因为调用泛型方法需要了解类型 T在编译时。相反,请使用
MethodInfo.MakeGenericMethod()
为 T 的特定
Type
创建对方法的封闭形式引用。Modify the GetItemByID method to itself be generic:
public static T GetItemByID<T>(int UID)
GetAllItems<typeof(T)>()
does not work, as you've noted, since calling generic methods requires knowledge of the type T at compile time. Instead, useMethodInfo.MakeGenericMethod()
to create a closed form reference to the method for a particularType
of T.如果您不介意其成本,那么可以使用 Reflection 来实现以下功能:
它基本上使用 Reflection 来检索名为
UID
的字段的值。仅当您无法更改
Article
或User
时才使用此选项,因为这些应该从一个接口继承以允许访问UID 字段而不必反映它们。
Here's something in Reflection if you don't mind its cost:
It basically uses Reflection to retrieve the value of a field called
UID
.Use this only if you don't have the ability to change
Article
orUser
, since those should be inheriting from one interface to allow access to aUID
field without having to reflect them.不确定它是否适合您的系统,但您是否考虑过实现 KeyedCollection 而不仅仅是通用列表?
http://msdn.microsoft.com/en-us /library/ms132438%28VS.95%29.aspx
或者可能会从基类代码中深入了解自定义解决方案。
Not sure if it fits into your system as is, but have you thought about implementing a KeyedCollection instead of just a generic list?
http://msdn.microsoft.com/en-us/library/ms132438%28VS.95%29.aspx
Or there might be some insight into a custom solution from the base class code.
针对您的 1A,通常的解决方案是将 UID 属性提取到
Article
、User
和其他任何内容都实现的文件中;然后添加约束如果您无法控制
Article
、User
等类型,并且无法让它们实现此接口,那么您'基本上是**,并且您将无法以类型安全的方式执行此操作。In response to your 1A, the usual solution is to extract the UID property into an
which both
Article
,User
, and whatever else implement; and then add a constraintIf you don't have control over the types
Article
,User
, et al, and you can't make them implement this interface, then you're basically ** and you won't be able to do this in a typesafe way.我这样做的方法是使用 lambda。也许我过于简化了您实际想要完成的任务,但以下是我在 MVC5 应用程序中通过 Id 从列表中获取对象的方法:
当然,这是简化的示例,但我认为这可能会派上用场提问者或其他人。
The way I'm doing it is by using a lambda. Maybe I'm over-simplifying what you actually want to accomplish, but here's how I'm getting an object out of a list by its Id in an MVC5 app:
Simplified example, of course, but thought this may come in handy for the Questioner or others.
System.Type已经是一个类型,不需要做typeof。
那么我会这样做:
if (T == typeof(文章))
item = ((List)mainList).Find(vr => vr.UID == UID);
System.Type is already a type, no need to do typeof.
then I would do:
if (T == typeof(Article))
item = ((List)mainList).Find(vr => vr.UID == UID);