我有一个通用工厂
public interface IViewModelFactory<T> where T : IViewModel
{
T Create<TU>(TU par);
}
public class ViewModelFactory<T> : IViewModelFactory<T> where T : IViewModel
{
private readonly ILifetimeScope _scope;
public ViewModelFactory(ILifetimeScope scope)
{
_scope = scope;
}
public T Create<TU>(TU par)
{
return _scope.Resolve<T>(new TypedParameter(typeof(TU), par));
}
}
我可以用它来解决在我的窗口类中的视图模型工厂问题:
public WRPersons(IViewModelFactory<MRPersons> viewModelFactory)
{
var viewModel = viewModelFactory.Create(new MRPersonsUseCaseParams { Filter = 2 });
...
}
ViewModel是通过以下代码实现的
public class MRPersons : IViewModel
{
public MRPersons(MRPersonsUseCaseParams par)
{
_filter = par.Filter;
}
}
public class MRPersonsUseCaseParams
{
public int Filter { get; set; }
}
我的组合根中的注册过程如下:
var builder = new ContainerBuilder();
builder.RegisterType<ViewModelFactory<MRPersons>>().As<IViewModelFactory<MRPersons>>();
builder.RegisterType<MRPersons>();
正如您所看到的,对于每个新的ViewModel(现在只有MRPerson),我都需要在组合根中创建两个条目。 因此,对于MRCar,它将是:
builder.RegisterType<ViewModelFactory<MRCar>>().As<IViewModelFactory<MRCar>>();
builder.RegisterType<MRCar>();
我希望能以某种方式自动化这些注册。我尝试使用RegisterAssemblyTypes/AsClosedTypesOf进行实验,但没有成功。有人可以帮助我吗?
编辑:根据答案代码行。
builder.RegisterType<ViewModelFactory<MRPersons>>().As<IViewModelFactory<MRPersons>>();
被替换为
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
完全自动注册的过程如下:
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).AsSelf();
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
为了更好的可测试解决方案,最好将MRPersons替换为IMRPersons:
public class MRPersons : IViewModel, IMRPersons
{
public MRPersons(MRPersonsUseCaseParams par)
{
_filter = par.Filter;
}
}
public class MRPersonsUseCaseParams
{
public int Filter { get; set; }
}
public interface IMRPersons
{
}
因此,在组合根中进行注册的方式应该是这样的(需要进行更正)。
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).As<??????>.AsSelf();
这将允许我以以下方式将工厂传递到构造函数中:
public WRPersons(IViewModelFactory<IMRPersons> viewModelFactory)
{
var viewModel = viewModelFactory.Create(new MRPersonsUseCaseParams { Filter = 2 });
...
}
编辑2: 与Cyril Durand聊天期间,他提供了一种不需要引用ILifetimeScope的ViewModelFactory解决方案。以下是代码:
public interface IViewModelFactory2<T, TU> where T : IViewModel
{
T Create(TU par);
}
public class ViewModelFactory2<T, TU> : IViewModelFactory2<T, TU> where T : IViewModel
{
private readonly Func<TU, T> _factory;
public ViewModelFactory2(Func<TU, T> factory)
{
_factory = factory;
}
public T Create(TU par)
{
return _factory(par);
}
}
我的原始工厂也可以,因为它出现在组成根目录中,可以使用对DI容器的强引用。
IViewModelFactory<MRPersons>
,您不需要注册MRPersons
。Autofac 不需要这种类型。 - Cyril Durand