在 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);
}

但是我从 dynamicIDocumentEntity 收到 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; }