我有一些想要創建的 EF 模型類。每個類都有一些我想在插入新物體之前設定的公共屬性,例如:
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,
...
};
...
我想創建一個方法來自動設定一些公共屬性,這樣我就不需要為每個具有相同屬性的類手動輸入它們。由于它們不擴展相同的類或實作相同的介面,我想知道如何實作這一點。我的第一個想法是使用泛型方法;但是,我不知道是否有一種方法可以指定泛型型別應該具有哪些屬性而不擴展相同的類(類似于 TypeScript 的“鴨子型別”)。我想要的方法看起來像這樣:
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; 但是,如果可能,我想繼續進行型別檢查。
uj5u.com熱心網友回復:
你可以使用反射來實作你想要的。例如,您可以傳入一個物件并決議它的型別,然后獲取該給定型別的所有公共屬性并查找是否有一個被呼叫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);
}
從長遠來看,您最好創建一個通用介面甚至抽象基類,這樣您就不必為每個 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;
}
一旦你開發了一個介面,你可以獲得比使用反射或動態型別更大的靈活性,因為你得到了我之前提到的編譯時檢查,你可以看到你的模型的公共屬性。
uj5u.com熱心網友回復:
您不能在 C# 中這樣做,因為 C# 使用名義型別系統而不是結構型別系統。
對于您的特定情況,您必須提出一個包含共同屬性的介面,并且將由兩個物體實作,然后使用該新介面作為通用函式引數約束。
uj5u.com熱心網友回復:
如果您絕對確定屬性將具有相同的名稱,則可以傳遞 adynamic來設定屬性值。但是,這會阻止對型別進行任何編譯時檢查,因此如果您不小心傳遞了一個不兼容的型別,它在運行時之前不會被捕獲。
public void SetInitialProperties(dynamic dbEntity, DateTime createdTime, string creatorName) {
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/323510.html
上一篇:TLS 基礎知識 (1)
下一篇:Java擴展引數化類
