2017-09-07 32 views
1

我會盡我所能解釋這一點。約束違規,列表<Model<Type1>>至列表<Model<Type2>>

轉換:

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

類型定義:

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 

什麼我想實現:

轉換模型列表類型SqlDbAccess到SQLiteDbAccess,反之亦然。

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

來電:

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

錯誤:

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

爲什麼'typeof(TD)'而不是'typeof(TDest).GetType().GetGenericArguments()[0]'? – ASpirin

+0

@ASpirin這是我的錯誤,現在它已經修復了。 – NullBy7e

+0

@ NullBy7e你的示例似乎對我有用,我把你的代碼添加了缺失的類體並試圖重現,我唯一需要做的改變就是將'GetType()'從'typeof(TDest).GetType ).GetGenericArguments()[0]; ' –

回答

1

,定義如下解決:

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>