在asp.net核心mvc项目中,我有一个抽象的ViewModel
类用于布局,需要一些属性才能正常运行,而每个具体页面的{{1} }从中得出:
ViewModel
布局需要public abstract class Layout
{
// required to function properly
public string Prop1 { get; set; }
// required to function properly
public IEnumerable<Foo> FooList { get; set; }
protected Layout()
{
// Populate FooList from an util caching class?
}
}
public class ViewModelHome : Layout {}
public class ViewModelProducts : Layout {}
,因为它是不经常更改的数据,所以它是从数据库或缓存中填充的。
我想避免将每个必填字段放在构造函数中,以使其不太冗长,并且我想避免对每个派生类进行以下操作:
FooList
在asp.net中,核心缓存可以通过var model = new ViewModelHome();
model.FooList = .....
的DI来获得,所以我不能这样写:
IMemoryCache
这是因为我是在服务中自己创建 public abstract class Layout
{
protected Layout()
{
var cacheClass = new MyCacheClass(...IMemoryCache??...);
this.FooList = cacheClass.GetFooList();
}
}
,然后从控制器中调用。
Layout
我的问题是:我应该将抽象类构造函数中的逻辑从数据库或缓存中获取吗?
谢谢
答案 0 :(得分:3)
在视图模型中具有依赖项是一个糟糕的设计。我的理解是,您想为所有视图模型设置一些通用属性。为了解决这个问题,我建议您实现某种初始化器(例如IViewModelInitializer
),然后可以将其注入控制器中,然后对所有视图模型进行调用以对其进行初始化。您可以在此初始值设定项中注入所有依赖项(缓存,存储库等)。请参见下面的代码示例:
public class Foo { }
public class Bar { }
public abstract class Layout
{
public Bar Bar { get; set; }
public IEnumerable<Foo> FooList { get; set; }
}
public class HomeViewModel : Layout
{
}
public interface IFooRepository
{
IEnumerable<Foo> GetList();
}
public interface IBarRepository
{
Bar GetSingle();
}
public interface ILayoutInitializer
{
void Initialize(Layout layout);
}
public class LayoutInitializer : ILayoutInitializer
{
private readonly IFooRepository _fooRepository;
private readonly IBarRepository _barRepository;
public LayoutInitializer(IFooRepository fooRepository, IBarRepository barRepository)
{
_fooRepository = fooRepository;
_barRepository = barRepository;
}
public void Initialize(Layout layout)
{
if (layout is null) throw new ArgumentNullException(nameof(layout));
layout.FooList = _fooRepository.GetList();
layout.Bar = _barRepository.GetSingle();
}
}
public class MainController : Controller
{
private readonly ILayoutInitializer _layoutInitializer;
public MainController(ILayoutInitializer layoutInitializer)
{
_layoutInitializer = layoutInitializer;
}
public IActionResult Home()
{
var homeViewModel = new HomeViewModel();
_layoutInitializer.Initialize(homeViewModel);
return View(homeViewModel);
}
}
答案 1 :(得分:1)
我想您在这里有几个选择:
IMemoryCache
注入属性中,我不推荐这种方法。public class Foo {
[Inject] // or other marker attribute specific to your IoC
public readonly IMemoryCache;
....
}
public Foo(): base()
{
base.MemoryCache = IoC.Resolve<IMemoryCache>();
}
public Foo(IMemoryCache cache): base(cache)
public void Foo(IMemoryCache cache, int bar)
public Foo(IBar bar, IBaz baz, IContainer container): base(container)
{
...
}
在重重构期间,我遇到了选项5效果最好的情况。