2017-09-07 2 views
1

Je vais essayer d'expliquer cela aussi bien que je peux.Contrainte violation, Liste <Model<Type1>> Liste <Model<Type2>>

Conversion:

Source type:  List<ConfigurationProcessFilterModel<SqlDbAccess>> 
Destination type: List<ConfigurationProcessFilterModel<SQLiteDbAccess>> 

définitions de type:

abstract class BaseEntityModel<T> : INotifyPropertyChanged where T : IDbAccess 
class ConfigurationProcessFilterModel<T> : BaseEntityModel<T> where T : IDbAccess 
class SqlDbAccess : SQLBase, IDbAccess 
class SQLiteDbAccess : SQLBase, IDbAccess 
abstract class SQLBase 
interface IDbAccess 

Qu'est-ce que je veux atteindre:

Convertir une liste des modèles de type SqlDbAccess à SQLiteDbAccess et vice-versa.

ModelConverter:

public class ModelConverter<TS, TD> 
    where TS : SQLBase, IDbAccess 
    where TD : SQLBase, IDbAccess 
{ 
    public static TDest Convert<TSource, TDest>(object source) 
     where TSource : List<BaseEntityModel<TS>>, new() 
     where TDest : List<BaseEntityModel<TD>>, new() 
    { 
     var sourceModel = (TSource)source; 
     var destModel = new TDest(); 
     var destInnerType = typeof(TDest).GetType().GetGenericArguments()[0]; 

     foreach (var sourceItem in sourceModel) 
     { 
      var destItem = (BaseEntityModel<TD>)Activator.CreateInstance(destInnerType); 
      destModel.Add(destItem); 
     } 

     return destModel; 
    } 
} 

appelant:

if (property.PropertyType.IsEnumerable()) 
{ 
    var innerType = 
     property.PropertyType.GetGenericArguments()[0].GetGenericArguments()[0]; 
    if(innerType == typeof(SqlDbAccess)) 
    { 
     //List<BaseEntityModel<SqlDbAccess>> 
     var sourceType = property.PropertyType; 
     var sourceModelType = sourceType.GetGenericArguments()[0]; 

     //List<BaseEntityModel<SQLiteDbAccess>> 
     var destinationModelType = sourceModelType.GetGenericTypeDefinition() 
      .MakeGenericType(typeof(SQLiteDbAccess)); 
     var destinationType = typeof(List<>) 
      .MakeGenericType(destinationModelType); 

     var method = typeof(ModelConverter<SqlDbAccess, SQLiteDbAccess>) 
      .GetMethod("Convert"); 
     var generic = method.MakeGenericMethod(sourceType, destinationType); 
     model = generic.Invoke(this, new object[] { model }); 
    } 
} 

Erreur:

System.ArgumentException: 'GenericArguments[0], 'System.Collections.Generic.List 1[Data.Models.ConfigurationProcessFilterModel 1[Data.Database.SqlDbAccess]]', on 'TDest ConvertTSource,TDest' violates the constraint of type 'TSource'.'

Inner Exception:
VerificationException: Method Data.ModelConverter 2[Data.Database.SqlDbAccess,Data.Database.SQLiteDbAccess].Convert: type argument 'System.Collections.Generic.List 1[Data.Models.ConfigurationProcessFilterModel`1[Data.Database.SqlDbAccess]]' violates the constraint of type parameter 'TSource'.

+0

pourquoi pas 'typeof (TD)' au lieu de 'typeof (TDest) .GetType(). GetGenericArguments() [0]'? – ASpirin

+0

@ASpirin c'était une erreur de ma part, c'est corrigé maintenant. – NullBy7e

+0

@ NullBy7e votre échantillon semble fonctionner pour moi, j'ai pris votre code ajouté les corps de classe manquants et j'ai essayé de reproduire, le seul changement que j'ai dû faire était de couper le 'GetType()' from typeof (TDest) .GetType () .GetGenericArguments() [0]; ' –

Répondre

1

résolu avec la définition suivante:

public static TDest Convert<TSource, TDest, TS1, TS2>(object source) where TSource : List<TS1>, new() where TDest : List<TS2>, new() where TS1 : BaseEntityModel<TS> where TS2 : BaseEntityModel<TD>