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)));