简体   繁体   English

使用反射在通用存储库中提升派生实体

[英]Using Reflection to Upsert Derived Entities in Generic Repository

A bit new at the Repository Pattern. 存储库模式中的新功能。 Trying to build a generic repository that will also handle state changes to derived entities. 尝试构建通用存储库,该存储库还将处理对派生实体的状态更改。 What I've done so far is create a custom attribute to flag the property as one which needs to be upserted. 到目前为止,我所做的是创建一个自定义属性,以将该属性标记为需要向上插入的属性。

Attribute: 属性:

public class DerivedObjectAttribute : Attribute
{
    public enum EntityType
    {
        REFERENCE,
        OBJECT
    }

    public EntityType DerivedType { get; set; }
}

I define this attribute for any property on which I want to cascade state changes. 我为要在其上级联状态更改的任何属性定义此属性。

Sample Entity: 样本实体:

public class FightingCharacter : BaseEntity 
{
    public Costume costume { get; set; }

    [DerivedObject(DerivedType=DerivedObjectAttribute.EntityType.REFERENCE)]
    public SpecialFinish specialFinish { get; set; }

    [DerivedObject(DerivedType = DerivedObjectAttribute.EntityType.REFERENCE)]
    public List<MoveList> moveList { get; set; }
}

So for this class, the costume property would not need to cascade, but the specialFinish and moveList properties should. 因此,对于此类,不需要服装属性,而应该使用specialFinish和moveList属性。

Then in my repository: 然后在我的存储库中:

public class DataRepository<T> : IRepository<T> where T : BaseEntity {
    private void TryDerivedUpsert(T entity)
    {
        Type type = entity.GetType();
        PropertyInfo[] piList = type.GetProperties();
        foreach (PropertyInfo pi in piList)
        {
            foreach (DerivedObjectAttribute attr in pi.GetCustomAttributes(typeof(DerivedObjectAttribute), false))
            {
                // What to do here?
            }
        }
    }
}

In the innermost loop, I'm able to pinpoint DerivedObjectAttributes without any problem. 在最内层的循环中,我可以毫无问题地精确定位DerivedObjectAttributes。 The question is: how do I obtain the Type and Value of the object, then upsert it? 问题是:如何获取对象的类型和值,然后对其进行向上插入? In other words: if property pi is flagged to cascade changes, create a repo cast to the appropriate Entity, and Upsert it. 换句话说:如果将属性pi标记为级联更改,请创建对适当实体的存储库,并对其进行Upsert。 EG: 例如:

DataRepository<EntityType> repo = new DataRepository<EntityType> ();
repo.Upsert(property as EntityType);

Does that make sense? 那有意义吗? Or am I going about generic repo entirely the wrong way? 还是我会以完全错误的方式进行通用回购? If it does make sense (I'll be surprised), how to do it? 如果确实有意义(我会感到惊讶),该怎么做? (The examples listed here are just examples, BTW. I'm still architecting and have no EF classes at all yet.) (这里列出的示例只是示例,顺便说一句。我仍在进行架构设计,根本没有EF类。)

You could get the value with pi.GetValue(entity, null) , and create the generic repository ( Activate.CreateInstance ) for the property type (from pi), but you will have to do a lot of reflection. 您可以使用pi.GetValue(entity, null)来获取值,并为属性类型(来自pi)创建通用存储库( Activate.CreateInstance ),但是您将不得不进行很多反思。

In this case you should think about dropping the classic generic repository idea (separate repository per type) and use something like an extended DbContext , that can handle all types. 在这种情况下,您应该考虑放弃经典的通用存储库想法(每种类型使用独立的存储库),并使用可处理所有类型的扩展DbContext类的东西。

If you have a disconnected scenario (WCF), the main problem will be EF itself, because you have to replicate all changes to nested lists on the server side and manually change the EntityState. 如果您具有断开连接的方案(WCF),则主要问题将是EF本身,因为您必须将所有更改复制到服务器端的嵌套列表中并手动更改EntityState。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM