解决通用的IEnumerable的构造函数中使用Autofac
所以我有一个抽象工厂类的,这种想法是,在这家工厂的构造,我会从autofac所有已注册的服务我很感兴趣的IEnumerable
通过在这个工厂有一个传递参数的方法,代码将遍历IEnumerable
并返回匹配的服务。容易如馅饼,抽象的工厂模式。解决通用的IEnumerable的构造函数中使用Autofac
的问题是,我最近在我的接口工厂返回引入了泛型类型,我不知道怎么写的构造函数,因此autofac知道所有已注册的服务仍然会返回,而忽视了基本上是泛型。
一些代码:
我的接口:
public interface IRunnerServices<in T>
{
void Create(T entity);
}
接口
public class RunnerServiceA : IRunnerServices<A>
{
public void Create(A entity);
}
public class RunnerServiceB : IRunnerServices<B>
{
public void Create(B entity);
}
public class RunnerServiceC : IRunnerServices<C>
{
public void Create(C entity);
}
// Many, many more...
而且我的作文根的某些实现,我注册了这些服务,这样
builder.RegisterType<RunnerServicesA>().As<IRunnerServices<A>>();
builder.RegisterType<RunnerServicesB>().As<IRunnerServices<B>>();
builder.RegisterType<RunnerServicesC>().As<IRunnerServices<C>>();
而只是让你知道,A,B,C都来自同一个基类继承
public class A : LetterBase
{ }
public class B : LetterBase
{ }
public class C : LetterBase
{ }
现在,我的抽象工厂
public class RunnerServicesFactory
{
private readonly IEnumerable<IRunnerServices<????>> _candidates;
public RunnerServicesFactory(IEnumerable<IRunnerServices<????>> candidates)
{
_candidates = candidates;
}
public IRunnerServices<????> Create(int discriminator)
{
return _candidates.First(c => c.Discriminator == discriminator);
}
}
问题出在什么地方做我在构造上面提供和其他声明在????让autofac知道它应该通过这个通用的所有注册服务?
我想这一点,但没有运气autofac通过什么
IEnumerable<IRunnerServices<LetterBase>>
为了投你RunnerServiceA
实施IRunnerService<LetterBase>
你需要IRunnerService<T>
协与出通用关键字改性剂,它不因为您有一种方法可以接受T
参数。
。净不允许你投RunnerServiceA
到IRunnerService<LetterBase>
您可以通过这个简单的代码尝试:
var runnerService = (IRunnerServices<LetterBase>)new RunnerServiceA();
// Throws an InvalidCastException
一个可能的解决办法是让IRunnerService<T>
协这样的:
public interface IRunnerServices<out T>
where T : LetterBase
{
void Create(LetterBase entity);
}
通过这样做,你将能够投RunnerServiceA
到IRunnerService<LetterBase>
,做这样的代码:
IEnumerable<IRunnerServices<LetterBase>> runners = new IRunnerServices<LetterBase>[] {
new RunnerServiceA(),
new RunnerServiceB()
};
然后Autofac就能解决IEnumerable<IRunnerServices<LetterBase>>
如果RunnerService
注册为IRunnerServices<LetterBase>
顺便问一下你在做什么,让我想想IIndex<TKey, T>
:
public class RunnerServicesFactory
{
private readonly IIndex<Char, IRunnerServices<LetterBase>> _candidates;
public RunnerServicesFactory(IIndex<Char, IRunnerServices<LetterBase>> candidates)
{
_candidates = candidates;
}
public IRunnerServices<LetterBase> Create(Char discriminator)
{
return _candidates[discriminator];
}
}
和登记将是这样的:
builder.RegisterType<RunnerServiceA>().Keyed<IRunnerServices<LetterBase>>('A');
builder.RegisterType<RunnerServiceB>().Keyed<IRunnerServices<LetterBase>>('B');
builder.RegisterType<RunnerServiceC>().Keyed<IRunnerServices<LetterBase>>('C');
我并不完全了解你的covarient解决方案,你是否输错了什么。你声明IRunnerServices
@raterus'out'修饰符仅用于允许.net将'RunnerServiceA'强制转换为'IRunnerService
你想要的是同时使用协变和逆变,这是不可能的。你需要变相吗? –