访问泛型实例属性


如何

访问instanceId属性?我有以下代码:

public void InsertOrUpdate(Book book)
{
    if (book.Id == default(int)) {

我现在想让它通用:

public class TheRepository<T> : IRepository<T> where T : class
{
    public void InsertOrUpdate(T instance)
    {
        if (instance.Id == default(int))//How can I access Id here
        {
            context.Set<T>().Add(instance);

搜索了类似的帖子,我想我应该写一些类似instance.GetType().GetProperty("Id").GetValue()但我不知道具体如何?

你可以做这样的黑客。定义一个接口,其中只有一个类型为 int 的属性称为 Id

interface IHaveId
{
    public int Id { get; set; }
}

然后声明您的实体实现接口:

public class Book : IHaveId

泛型存储库类中使用的类型应实现此接口的最后状态。

public class TheRepository<T> : IRepository<T> where T : class, IHaveId
{
    public void InsertOrUpdate(T instance)
    {
        if (instance.Id == default(int))
        {
            context.Set<T>().Add(instance);
        }
    }
}

这样做可以避免使用反射,这在一般情况下是非常昂贵的。此外,您的代码现在更加清晰。

目前,编译器对T一无所知,只知道它是一个类。这意味着它永远无法知道它有一个Id属性,因为没有什么能阻止你创建一个TheRepository<string>的实例 - 当然,它没有Id属性。

您在答案中提到的代码片段,使用反射,是一个好方法。正如我所提到的,如果您创建一个字符串存储库,会发生什么?此代码必然会失败,因为字符串没有 Id 属性。

在这种情况下,您需要做的是确保类Book以及您需要在存储库中保留的任何其他实体实现包含 ID 的基类:

public abstract class DataObject
{
    public int Id {get;set;}
}
public class Book : DataObject
{}

现在,您可以将存储库限制为继承DataObject的类:

public class TheRepository<T> : IRepository<T> where T : DataObject

现在,编译器可以确信,无论 T 是什么,T 的任何实例始终继承DataObject,因此具有Id属性。

最新更新