假设我有以下实现以下接口的类:
class MyClassA : IInterface<MyClassA>, IInterface
class MyClassB : IInterface<MyClassB>, IInterface
我还有另外两个类似的类:
class ImportA {
public ImportA(IEnumerable<IInterface>) {}
}
class ImportB {
public ImportB(IInterface<MyClassA>) {}
}
我希望ImportA随我的程序集中实现
IInterface
的每个类一起注入。我希望ImportB仅注入
IInterface<MyClassA>
实例。我希望来自这两种方法的具体类MyClassA的实例相同(生命周期:单例)。
我不知道如何使它与Simple Injector一起使用。我已经尝试过
RegisterCollection
和https://simpleinjector.readthedocs.org/en/latest/howto.html#register-multiple-interfaces-with-the-same-implementation我最接近的错误是说一个类作为Singleton导入而另一个类作为Transient导入。
我尝试将所有LifeStyles更改为Singleton,并将配置默认设置为Singleton,无济于事。
更新1:
我正在寻找一种自动化的方法。我有很多课程要注册,不想手工做。这是一个不同的示例。以下注册示例无效。自动执行失败的原因是:
An exception of type 'SimpleInjector.ActivationException' occurred in
SimpleInjector.dll but was not handled in user code
Additional information: The constructor of type MyClassB contains the
parameter with name 'myClassA' and type IInterface<MyClassA> that is not
registered. Please ensure IInterface<MyClassA> is registered, or change the
constructor of MyClassB. There is, however, a registration for
IEnumerable<IInterface<MyClassA>>; Did you mean to depend on
IEnumerable<IInterface<MyClassA>>?
这是我当前的代码:
public interface IInterface {
string Value { get; set; }
}
public interface IInterface<T> : IInterface { }
public class MyClassA : IInterface<MyClassA> {
public string Value { get; set; }
}
public class MyClassB : IInterface<MyClassB> {
private IInterface<MyClassA> myClassA;
public MyClassB(IInterface<MyClassA> myClassA) {
this.myClassA = myClassA;
}
public string Value {
get { return this.myClassA.Value; }
set { this.myClassA.Value = value; }
}
}
public class ImportA {
public ImportA(IEnumerable<IInterface> imports) {
// fails on this line
var a = imports.SingleOrDefault(i => i is IInterface<MyClassA>);
a.Value = "test";
var b = imports.SingleOrDefault(i => i is IInterface<MyClassB>);
// should output the value of "test";
Console.WriteLine(b.Value);
Console.ReadKey();
}
}
...
static void Main() {
var container = new Container();
var types = container.GetTypesToRegister(
typeof(IInterface<>), new[] { typeof(IInterface<>).Assembly });
var registrations = (
from type in types
select Lifestyle.Singleton.CreateRegistration(type, type, container))
.ToArray();
container.RegisterCollection<IInterface>(registrations);
container.RegisterCollection(typeof(IInterface<>), registrations);
var a = container.GetInstance(typeof(ImportA));
}
ImportA是入口点,应该是瞬态的。
其他所有内容都应为单例,以便在ImportA中修改MyClassA时,将在MyClassB中获取该值。
最佳答案
完成此操作的方法是手动创建Registration
实例,并使用它们注册两个单独的集合。例:
var a = Lifestyle.Singleton.CreateRegistration<MyClassA>(container);
var b = Lifestyle.Singleton.CreateRegistration<MyClassB>(container);
container.RegisterCollection<IInterface>(new[] { a, b });
container.AddRegistration(typeof(IInterface<MyClassA>), a);
container.AddRegistration(typeof(IInterface<MyClassB>), b);
这将确保两个集合中使用相同的单个实例。如果一个类实现
IInterface<T>
的多个通用版本,则同一实例甚至将在IInterface<T>
的不同集合上重用。如果您想要一种更自动化的方法,则可以执行以下操作:
var types = container.GetTypesToRegister(typeof(IInterface<>), assemblies);
// NOTE: The ToArray() call is crucial to prevent torn lifestyles.
var registrations = (
from type in types
select Lifestyle.Singleton.CreateRegistration(type, type, container))
.ToArray();
container.RegisterCollection<IInterface>(registrations);
foreach (var registration in registrations) {
container.AddRegistration(
typeof(IInterface<>).MakeGenericType(registration.ImplementationType),
registration);
}