C# 为实现接口的所有类型注册泛型工厂
我有一家仿制药厂C# 为实现接口的所有类型注册泛型工厂,c#,generics,dependency-injection,autofac,C#,Generics,Dependency Injection,Autofac,我有一家仿制药厂 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 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));
}
}
我的作文根目录中的注册如下所示:
var builder = new ContainerBuilder();
builder.RegisterType<ViewModelFactory<MRPersons>>().As<IViewModelFactory<MRPersons>>();
builder.RegisterType<MRPersons>();
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).AsSelf();
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
因此,组合根目录中的注册看起来像(需要更正)
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly())。其中(x=>iViewModelType.IsAssignableFrom(x)和&x.IsClass)。As.AsSelf();
这将允许我通过以下方式将工厂传递给构造函数:
public WRPersons(IViewModelFactory<IMRPersons> viewModelFactory)
{
var viewModel = viewModelFactory.Create(new MRPersonsUseCaseParams { Filter = 2 });
...
}
public WRPersons(IViewModelFactory视图模型工厂)
{
var viewModel=viewModelFactory.Create(新的MRPersonUseCaseParams{Filter=2});
...
}
EDIT2:
在与Cyril Durand聊天期间,他为ViewModelFactory提供了解决方案,而没有参考ILifetimeScope。下面是一个代码:
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);
}
}
公共接口IViewModelFactory2,其中T:IViewModel
{
T创建(tupar);
}
公共类ViewModelFactory2:IViewModelFactory2其中T:IViewModel
{
私有只读功能工厂;
公共视图模型工厂2(Func工厂)
{
_工厂=工厂;
}
公共T创建(TU par)
{
返回工厂(par);
}
}
我的原始工厂也可以,因为它是在composition root中显示的,可以使用对DI容器的强引用。如果要将
ViewModelFactory
注册为IViewModelFactory
,可以使用RegisterGeneric
方法
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
或者你可以使用一种约定,将所有X
注册为IX
,但我不太喜欢这种注册
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass)
.As(t => t.GetInterfaces().Where(i => i.Name.EndsWith(t.Name)));
顺便说一下,在聊天之后,我们发现你根本不需要
IViewModelFactory
,但你只需要依赖Func
哦,太好了,我完全错过了这个。您的解决方案可以很好地替换my builder.RegisterType().As();代码行。对于完整的解决方案(如果有人感兴趣)builder.RegisterType();可以由builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly())替换。其中(x=>iViewModelType.IsAssignableFrom(x)和&x.IsClass)。AsSelf();有没有办法注册MRPersons,MRCar。。。通过其特定接口下的自动代码IMRPersons、IMRCar?(当然,如果这个接口存在的话)。我的实际注册.AsSelf()现在就足够了,但对于更复杂的解决方案,如.As().AsSelf()之类的,其中IXXX是动态的,那就太好了。@user2126375为了解析IViewModelFactory
您不需要注册MRPersons
。Autofac不需要这种类型。@user2126375您能用第二个要求编辑您的问题(或发布新问题)吗?这将更容易阅读,我将编辑我的答案:)我必须注册。否则,我将获得ComponentNotRegisteredException“请求的服务'DITester.DI.MRPersons'尚未注册”。返回时,返回_scope.Resolve(new TypedParameter(typeof(TU),par));代码行。
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).AsSelf();
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
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 });
...
}
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);
}
}
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly())
.Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass)
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass)
.As(t => t.GetInterfaces().Where(i => i.Name.EndsWith(t.Name)));