我有很多接口,每个接口有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>();
这将使用typeparameter Foo 从数据库中返回所有ModelFoo。现在我想做以下事情:
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
答案 0 :(得分: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
),世界将会欣赏它。它确实使阅读代码更容易。祝你好运!