gpt4 book ai didi

c# - 有没有一种方法可以使用对象的形状而不是继承来对通用函数参数进行类型检查?

转载 作者:行者123 更新时间:2023-12-05 02:38:23 25 4
gpt4 key购买 nike

我有几个要创建的 EF 模型类。每个类都有一些我想在插入新实体之前设置的公共(public)属性,例如:

public partial class BlogPost {
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
public string PostTitle { get; set; }
public string PostText { get; set; }
}

public partial class Comment {
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
public string CommentText { get; set; }
}

...

当我创建这些类时,我会像这样实例化它们:

var blogPost = new BlogPost {
CreatedTime = DateTime.UtcNow,
CreatorName = creatorName,
PostTitle = postTitle,
PostText = postText,
};

var comment = new Comment {
CreatedTime = DateTime.UtcNow,
CreatorName = creatorName,
...
};

...

我想创建一个方法来自动设置一些通用属性,这样我就不需要为每个具有相同属性的类手动输入它们。由于它们不扩展相同的类或实现相同的接口(interface),我想知道如何实现这一点。我的第一个想法是使用通用方法;但是,我不知道是否有一种方法可以指定泛型类型在不扩展相同类的情况下应该具有哪些属性(类似于 TypeScript 的 "duck typing" )。我想要的方法看起来像这样:

public void SetInitialProperties<T>(T dbEntity, DateTime createdTime, string creatorName) where T : ??? {
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}

...

var blogPost = new BlogPost { PostTitle = postTitle, PostText = postText };
SetInitialProperties(blogPost, createdTime, creatorName);

如果我不能使用泛型,最坏的情况是我总是可以使用dynamic;但是,如果可能的话,我想继续进行类型检查。

最佳答案

您可以使用反射实现您想要的。您可以传入一个对象并解析它的类型,然后获取该给定类型的所有公共(public)属性,并查找是否有一个名为 CreatedTime 的对象。然后您可以在传递的 dbEntity 对象上设置给定属性的值。但是,我不推荐这种解决方案:

public void SetInitialProperties(object dbEntity, DateTime createdTime, string creatorName) {
// get the passed object's properties and find the one called CreatedTime
var createdTimePropertyInfo = dbEntity.GetType().GetProperties().Where(i => i.Name == "CreatedTime").FirstOrDefault();
// below line is equal to: dbEntity.CreatedTime = createdTime;
createdTimePropertyInfo.SetValue(dbEntity, createdTime);

var creatorNamePropertyInfo = dbEntity.GetType().GetProperties().Where(i => i.Name == "CreatorName").FirstOrDefault();
creatorNamePropertyInfo.SetValue(dbEntity, creatorName);
}

从长远来看,您最好创建一个公共(public)接口(interface)甚至抽象基类,这样您就不必为每个 EF 模型实现 CreatedTime 和 CreatorName 以及其他属性。它看起来像下面这样:

public interface IUserEntry
{
DateTime CreatedTime { get; set; }
string CreatorName { get; set; }
}

public abstract class UserEntryBase : IUserEntry
{
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
}

public partial class BlogPost : UserEntryBase
{
public string PostTitle { get; set; }
public string PostText { get; set; }
}

public partial class Comment : UserEntryBase
{
public string CommentText { get; set; }
}

你的 SetInitialProperties 会非常简单:

public void SetInitialProperties(IUserEntry dbEntity, DateTime createdTime, string creatorName)
{
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}

在接口(interface)上进行开发后,与使用反射或动态类型相比,您可以获得更大的灵 active ,因为您可以获得我之前提到的编译时检查,并且您可以看到模型的通用属性。

关于c# - 有没有一种方法可以使用对象的形状而不是继承来对通用函数参数进行类型检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69622708/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com