Bonjour,
Je cherche à faire un supergénéric...
Du code parlant plus facilement, GO :
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 
// Eléments de structure
    public abstract class Identifier
    {
        // Identifiant dans la base de données
        public int ID { get; set; }
    }
 
    public abstract partial class NNLinkHistory<TIdentifierA, TIdentifierB> : IHistory
        where IdentifierA : Identifier
        where IdentifierB : Identifier
    {
        // Identifiant de la première entité
        public int Identifier1ID { get; set; }
 
        // Lien de navigation vers la première entité
        public TIdentifierA Identifier1 { get; set; }
 
        // Identifiant de la seconde entité
        public int Identifier2ID { get; set; }
 
        // Lien de navigation vers la seconde entité
        Public TIdentifierB Identifier2 { get; set; }
 
        // Date d'association (Interface IHistory)
        public DateTime AssociationDate { get; set; } = DateTime.UtcNow;
 
        // Date de dissociation (Interface IHistory)
        public DateTime? DissociationDate { get; set; }
    }
 
// Objets utiles
    public class Object1 : Identifier
    {
        // V1
        public ICollection<O1O2H> Object2sV1 { get; set; } = new HashSet<O1O2H>();
        // V2
        public MyCollection<O1O2H> Object2sV2 { get; set; } = new MyCollection<O1O2H>();
    }
 
    public class Object2 : Identifier
    {
        // V1
        public ICollection<O1O2H> Object1sV1 { get; set; } = new HashSet<O1O2H>();
        // V2
        public MyCollection<O1O2H> Object1s { get; set; } = new MyCollection<O1O2H>();
    }
 
    public class O1O2H : NNLinkHistory<Object1, Object2>
    {
        public int OtherProperty{ get; set; }
    }

Ceux qui utilise un ORM reconnaitront un lien 0,N---0,N entre 2 tables. D'ailleurs tant que j'y suis, je précise que j'utilise EFCore 3.1.17 et que je ne puis monter sur la version 5 car le framework utilisé est le standard 4.8 incompatible... no comment

A cela, j'ai ajouté une méthode d'extension pour aller chercher la relation active
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
    public static TEntity GetActive<TEntity>(this ICollection<TEntity> histories, BaseDbContext ctx)
        where TEntity : class, IHistory
    {
        public NNLinkHistory<TIdentifierA, TIdentifierB> GetActive(DbContext ctx, bool isForceToReload = false)
         {
            // Si l'historique n'est pas null
            if (this.Count() > 0 || !isForceToReload)
                // Renvoyer l'historique
                return this.First();
 
            // Récupérer la propriété à utiliser par son type
            var property = ctx.GetType()
                              .GetProperties()
                              .FirstOrDefault(o => o.PropertyType == typeof(DbSet<NNLinkHistory<TIdentifierA, TIdentifierB>>));
 
            // Si la propriété n'a pas été trouvée
            if (property == null)
                // Générer une exception
                throw new InvalidCastException();
 
            var queryable = (IQueryable<NNLinkHistory<TIdentifierA, TIdentifierB>>)property.GetValue(ctx);
 
            // Mettre à jour l'historique
            Clear();
 
            if (query.Count() > 0)
                AddRange(query.ToList());
 
            // Renvoyer l'historique
            return this.OrderByDescending(o => o.AssociationDate).FirstOrDefault();
        }

Ca fonctionne impeccable mais j'aimerais pouvoir faire un objet à part entière pour pouvoir hériter de cet objet afin de définir une fonction GetActive légèrement différente pour une classe particulière :
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
    public class MyCollection<TNNLinkHistory> : List<TNNLinkHistory>
        where TNNLinkHistory : NNLinkHistory<TIdentifierA, TIdentifierB> // Là déjà l'IDE râle car il ne connait pas TIdentifierA et TIdentifierB
    {
        public NNLinkHistory<TIdentifierA, TIdentifierB> GetActive(DbContext ctx, bool isForceToReload = false)
         {
            // Si l'historique n'est pas null
            if (this.Count() > 0 || !isForceToReload)
                // Renvoyer l'historique
                return this.First();
 
            // Récupérer la propriété à utiliser par son type
            var property = ctx.GetType()
                              .GetProperties()
                              .FirstOrDefault(o => o.PropertyType == typeof(DbSet<NNLinkHistory<TIdentifierA, TIdentifierB>>));
 
            // Si la propriété n'a pas été trouvée
            if (property == null)
                // Générer une exception
                throw new InvalidCastException();
 
            var queryable = (IQueryable<NNLinkHistory<TIdentifierA, TIdentifierB>>)property.GetValue(ctx);
 
            // Mettre à jour l'historique
            Clear();
 
            if (query.Count() > 0)
                AddRange(query.ToList());
 
            // Renvoyer l'historique
            return this.OrderByDescending(o => o.AssociationDate).FirstOrDefault();
        }
   }

Mais là ça coince

Bien évidemment, il n'y a pas que la fonction GetActive, il y a entre autre SetActive (qui s'appuie sur GetActive) mais seule celle-ci sera différente (d'où l'intérêt de l'héritage).

Auriez-vous une idée ?