2017-09-20 26 views
1

我有很多接口,每個都有它2個實現:鑄造從一個2種泛型類型的其他

public interface Foo{/**/} 

public class ModelFoo : Foo {/**/} 

public class ViewModelFoo : Foo {/**/} 

現在我有一個泛型函數中有一個repositoryInterface和2個實現:

public interface Repository 
    { 
     ICollection<TModel> GetAll<TModel>(); 
    } 

    public class ModelRepository : Repository 
    { 
     private IDictionary<Type, Type> typeMapping = new Dictionary<Type, Type>(); 
     private DbContext context; 
     public ICollection<TModel> GetAll<TModel>() 
     { 
      var implType = typeMapping[typeof(TModel)]; 
      var ctxSet = context.Set(implType); 

      return new EFWrapCollection<TModel>(Enumerable.Cast<object>(ctxSet).ToList()); 
     } 

    } 

接口的第一個實現將加載數據庫中的所有模型。字典typemapping需要在接口類型和具體類型之間進行類型映射。 EFWrapCollection將參數包裝爲TModel類型。

typemapping有對如下:

(typeof(Foo), typeof(ModelFoo)), 
(typeof(Bar), typeof(ModelBar)), 
... 

的使用情況如下:

 var rep = new ModelRepository(context); 
     rep.GetAll<Foo>(); 

這將返回所有ModelFoo的從數據庫中與typeparameter 。現在,我要做到以下幾點:

public class ViewModelRepository : Repository 
    { 
     private IDictionary<Type, Type> typeMapping = new Dictionary<Type, Type>(); 
     private Repository repository; 
     public ICollection<TModel> GetAll<TModel>() 
     { 
      var result = repository.getAll<TModel>(); 
      //now i have the problem that i need a cast 
      //but I dont know hot to achieve it 
     } 
    } 

在這個倉庫類也有一個typemapping。此屬性包含接口類型和視圖模型類型之間的所有映射:

(typeof(Foo), typeof(ViewModelFoo)), 
(typeof(Bar), typeof(ViewModelBar)), 
..... 

演員應該是投給Viewmodeltype。我知道如何投2個具體類,但在這裏我有問題,這個存儲庫是通用的,我不知道類型。

編輯

爲什麼我需要投(或映射):

在數據庫中,只有類型模式的模式,我想投(或地圖)類型型號納入型號ViewModel

+1

看起來你應該做映射,而不是鑄造。 – juharr

+0

@juharr是的,映射也許是更好的術語。但我不知道如何實現這裏的映射 –

+1

我目前不確定你到底想要做什麼。你的方法'GetAll ()'返回'ICollection '。也許你可以在'repository.getAll ()'返回的值上調用'.ToList()'。但我相信這不是你所期望的。目前還不清楚如何決定返回'ModelFoo'還是'ViewModelFoo'。我的猜測是調用'repository.getAll ()'是錯誤的,令我困惑。也許你試着調用'repository.getAll ()'(不編譯:-),但是你不知道該怎麼做。我對嗎?是的,也許我可以幫助你。否:請澄清。 –

回答

0

你在混合蘋果和橘子。您不應該在存儲庫內跟蹤類型。存儲庫應該特定於它的工作類型。

您可以改爲創建一個通用存儲庫並將其傳遞給它應該使用的類型。上下文有一個通用的Set<T>方法,你可以充分利用:

public class Repository<T> 
{ 
    private DbContext context; 
    public ICollection<T> GetAll() 
    {    
     var items = context.Set<T>(); 
     return new EFWrapCollection<T>(items); 
    } 
} 

我不完全知道爲什麼你正在使用EFWrapCollection但我猜你有你的理由。

我猜你現在已經意識到,除非你適當地管理上下文的生命週期,否則傳遞EF對象並不是一個好主意。類型映射可以用許多不同的方式處理。我建議你看看AutoMapper。您可以創建對象映射爲你的類,讓AutoMapper做的大部分工作,那麼對於那些不那麼直接的屬性提供自定義映射:

https://cpratt.co/using-automapper-getting-started/

這是從一個快速的摘錄鏈接,給你一個想法:

public static class AutoMapperConfig 
{ 
    public static void RegisterMappings() 
    { 
     AutoMapper.Mapper.CreateMap<ModelFoo, ViewModelFoo>() 
      .ForMember(dest => dest.Author, 
         opts => opts.MapFrom(src => src.Author.Name)); 
    } 
} 

順便說一句,如果你按照慣例,世界將欣賞它,並用字母前綴的接口I(例如IRepository)。它確實使閱讀代碼變得更容易。祝你好運!