在 C# 中是否可以有额外的(忽略的)属性?
Is it possible to have extra (ignored) properties in C#?
我有一个 DocumentDb
数据库的存储库。我的文档都有一组通用属性,因此所有文档都实现了 IDocumentEntity 接口。
public interface IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
}
public class KnownDocument : IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
[JsonProperty("knownProperty")]
string KnownProperty { get; set; }
}
public class BaseDocumentRepository<T> where T : IDocumentEntity {
public Set(T entity) {
// ... stuff
}
}
这适用于我知道所有属性的 KnownDocument
。但是,当然,Document Db 的优点在于我不需要知道所有属性(在很多情况下我不需要)。
所以我的客户提交了这样的东西-
{unknownProperty1: 1, unknownProperty2: 2}
我想使用我的文档存储库更新此内容。
public OtherDocumentService() {
_otherDocumentService = new OtherDocumentRepository();
}
public UpsertDocument(dynamic entity) {
entity.id = new Guid();
entity.documentClassification = DocumentClassification.Other;
_otherDocumentRepository.Set(entity);
}
但是我从 dynamic
到 IDocumentEntity
收到 InvalidCastException。我认为这是因为动态对象上存在的额外属性,而不是 IDocumentEntity
接口上存在的额外属性?
我想做的是让我的文档实体保持动态开放状态,但依靠一些属性来维护它们。
传递给 UpsertDocument 的实体参数应该显式实现 IDocumentEntity 才能使代码正常工作,仅仅有一个 ID 属性 是不够的。
部分选项:
1) 可以申请代理:
public class ProxyDocumentEntity : IDocumentEntity
{
public dynamic Content { get; private set; }
public ProxyDocumentEntity(dynamic @content)
{
Content = @content;
}
public Guid Id
{
get { return Content.Id; }
set { Content.Id = value; }
}
}
...使用
public void UpsertDocument(dynamic entity)
{
entity.Id = new Guid();
repo.Set(new ProxyDocumentEntity(entity));
}
存储的文档将有嵌套对象属性,这可能是不可接受的
2)有一个动态创建代理的库https://github.com/ekonbenefits/impromptu-interface
并且不会像上面的解决方案那样制作额外的 属性 。
缺点将在性能上。
从技术上讲,它可能有 2 种方法:
public void UpsertDocument(IDocumentEntity entity){...}
public void UpsertDocument(dynamic entity){...}
所以第一个(快速)将适用于实现 IDocumentEntity 的对象,第二个(慢速)适用于其余对象。
但这有点猜测,因为我不知道您拥有的项目的整个代码库的详细信息。
如果您对如何命名这些动态属性有一定的灵活性,您可以将它们塞入对象的字典 属性 中:
public Dictionary<string, dynamic> extra { get; set; }
我有一个 DocumentDb
数据库的存储库。我的文档都有一组通用属性,因此所有文档都实现了 IDocumentEntity 接口。
public interface IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
}
public class KnownDocument : IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
[JsonProperty("knownProperty")]
string KnownProperty { get; set; }
}
public class BaseDocumentRepository<T> where T : IDocumentEntity {
public Set(T entity) {
// ... stuff
}
}
这适用于我知道所有属性的 KnownDocument
。但是,当然,Document Db 的优点在于我不需要知道所有属性(在很多情况下我不需要)。
所以我的客户提交了这样的东西-
{unknownProperty1: 1, unknownProperty2: 2}
我想使用我的文档存储库更新此内容。
public OtherDocumentService() {
_otherDocumentService = new OtherDocumentRepository();
}
public UpsertDocument(dynamic entity) {
entity.id = new Guid();
entity.documentClassification = DocumentClassification.Other;
_otherDocumentRepository.Set(entity);
}
但是我从 dynamic
到 IDocumentEntity
收到 InvalidCastException。我认为这是因为动态对象上存在的额外属性,而不是 IDocumentEntity
接口上存在的额外属性?
我想做的是让我的文档实体保持动态开放状态,但依靠一些属性来维护它们。
传递给 UpsertDocument 的实体参数应该显式实现 IDocumentEntity 才能使代码正常工作,仅仅有一个 ID 属性 是不够的。
部分选项:
1) 可以申请代理:
public class ProxyDocumentEntity : IDocumentEntity
{
public dynamic Content { get; private set; }
public ProxyDocumentEntity(dynamic @content)
{
Content = @content;
}
public Guid Id
{
get { return Content.Id; }
set { Content.Id = value; }
}
}
...使用
public void UpsertDocument(dynamic entity)
{
entity.Id = new Guid();
repo.Set(new ProxyDocumentEntity(entity));
}
存储的文档将有嵌套对象属性,这可能是不可接受的
2)有一个动态创建代理的库https://github.com/ekonbenefits/impromptu-interface 并且不会像上面的解决方案那样制作额外的 属性 。 缺点将在性能上。
从技术上讲,它可能有 2 种方法:
public void UpsertDocument(IDocumentEntity entity){...}
public void UpsertDocument(dynamic entity){...}
所以第一个(快速)将适用于实现 IDocumentEntity 的对象,第二个(慢速)适用于其余对象。 但这有点猜测,因为我不知道您拥有的项目的整个代码库的详细信息。
如果您对如何命名这些动态属性有一定的灵活性,您可以将它们塞入对象的字典 属性 中:
public Dictionary<string, dynamic> extra { get; set; }