mercredi 6 février 2019

Generic Collections of unknown (sub-class) types

I have a base abstract class (baseEntity), derived from an Interface. From this, I have many sub-classes - each actually represents a database table for NHibernate. Some sub-classes contain properties that are other baseEntity classes, and some contain properties that are lists of other baseEntity classes. For some of these list properties I converted from using ILIst/List to ISet/HashSet, to stop an NHIbernate exception seen after upgrading from an ancient version 'Cannot simultaneously fetch multiple bags' My question is not to do with NHIbernate :

public interface INhEntity;

public abstract class BaseEntity;

public class OrderItems : baseEntity
{
    // properties
}

public class Order : baseEntity
{
    public virtual ISet<OrderItems> OrderItems { get; set;}
    public Order()
    {
        OrderItems = new HashSet<OrderItems>();
    }
}

We use ISet/HashSet because this seemed an easy and safe way to get rid of tyhe multi-bag problem (The HashSet will quietly stop duplicates)

We also use messaging to send data between sites. Basically, each baseEntity is serialized. At the other end, we deserialize, use PropertyInfo, Type details etc to reconstruct the baseEntity sub-class Referring to the Order/OrderItem classes above, I need to create/access/get access to the OrderItem property. This is where the fun arrives:

When I am processing a Set property, I try accessing as per below:

private void ProcessSet(object entity, ListItem listItem, PropertyInfo property)
{
    //entity is an instance of the Order entity
    //listitem contains info I will use to update the order item
    //property is the OrderItems property. It has a vale of:
    //ISet`1[Full.NameSpace.OrderItem] OrderItem}

    var setInstance = GetOrCreateSetInstance(entity, property);
    ...processing
    setInstance.Add(AnOrderItemInstance); //NHibernate knows to link the 2 database tables (OrderItems class does not need/have a FK)
}

private static ISet<baseEntity> GetOrCreateSetInstance(object entity, PropertyInfo prop)
{
    var listInstance = prop.GetValue(entity, null); // This looks just what I want
    var result = (ISet<baseEntity>)listINstance //cannot cast type OrderItem to baseEntity
    return result
}

I have similar code to deal with lists. Because I can return a non-generic Ilist, this works a treat. Prior to upgrading NHibernate, I was using the Iesi Isets, so my GetOrCreateINstance had this signature:

private static Iesi.Collection.ISet GetOrCreateSetInstance(object entity, PropertyInfo prop)

Is there anyway I can have a method to return the various subclass instances. Note I have tried returning HashSet, Iset/HashSet

I have tried Casting in various methods, but usually end up with '.. is a variable but is used like a type', I actually don't think it's possible, but any feedback most welcome





Aucun commentaire:

Enregistrer un commentaire