C# 如何使用simple injector将具有接口的类型注册为singleton?

C# 如何使用simple injector将具有接口的类型注册为singleton?,c#,dependency-injection,simple-injector,C#,Dependency Injection,Simple Injector,我有如下模型: public interface IUserLookupService { Guid[] GetDirectChilds(Guid userId); Guid[] GetAllChilds(Guid userId); Guid GetDepartment(Guid userId); } public interface ICanRefreshCache{ void Refresh(); } public class XHandler : IEv

我有如下模型:

public interface IUserLookupService {
    Guid[] GetDirectChilds(Guid userId);
    Guid[] GetAllChilds(Guid userId);
    Guid GetDepartment(Guid userId);
}

public interface ICanRefreshCache{
    void Refresh();
}

public class XHandler : IEventHandler<UserNameChanged> { ... }
public class YHandler : IEventHandler<TeamCreated> { ... }

public class CachedUserLookupService
    : IUserLookupService,
    ICanRefreshCache,
    IEventHandler<UserNameChanged>
{
    private Func<ISession> _sessionFactory;
    private IDictionary<Guid, UserInfo> _users = new Dictionary<Guid, UserInfo>();

    public CachedUserLookupService(Func<ISession> sessionFactory) {
        _sessionFactory = sessionFactory;
    }

    public void Handle(UserNameChanged ev) {
        // change cache with new event parameters
    }

    public void Refresh() {
        var session = _sessionFactory();
        // get user from db then create userinfo...
    }

    public Guid[] GetDirectChilds(Guid userId) {
        // code
    }

    public Guid[] GetAllChilds(Guid userId) {
           // code
    }

    public Guid GetDepartment(Guid userId) {
        // code
    }

    public class UserInfo
    {
        public Guid Id { get; set; }
        public string FullName { get; set; }
        public Guid? ParentId {get;set;}
    }
}

public class CachedTeamService
    : ITeamService,
    ICanRefreshCache,
    IEventHandler<TeamCreated>{
    // similar with CachedUserLookupService
}
公共接口IUserLookupService{
Guid[]GetDirectChilds(Guid用户ID);
Guid[]GetAllChilds(Guid用户ID);
Guid GetDepartment(Guid用户ID);
}
公共接口缓存{
无效刷新();
}
公共类XHandler:IEventHandler{…}
公共类YHandler:IEventHandler{…}
公共类CachedUserLookupService
:IUserLookupService,
我的缓存,
伊文坦德勒
{
私人Func_sessionFactory;
私有IDictionary_users=新字典();
公共CachedUserLookupService(Func sessionFactory){
_sessionFactory=sessionFactory;
}
公共无效句柄(用户名已更改){
//使用新的事件参数更改缓存
}
公共无效刷新(){
var session=_sessionFactory();
//从数据库获取用户,然后创建用户信息。。。
}
公共Guid[]GetDirectChilds(Guid用户ID){
//代码
}
公共Guid[]GetAllChilds(Guid用户ID){
//代码
}
公共Guid GetDepartment(Guid用户ID){
//代码
}
公共类用户信息
{
公共Guid Id{get;set;}
公共字符串全名{get;set;}
公共Guid?父ID{get;set;}
}
}
公共类CachedTeamService
:ITeamService,
我的缓存,
伊文坦德勒{
//与CachedUserLookupService类似
}
我的注册:

container.RegisterManyForOpenGeneric(typeof(IEventHandler<>),
    (closedServiceType, implementations) =>
    {
        container.RegisterAll(closedServiceType, implementations);
    },
    applicationAssembly, typeof(Constants).Assembly);

var serviceRegistrations = 
    from type in applicationAssembly.GetExportedTypes()
    where type.Name.EndsWith("Service")
    where !type.IsAbstract
    where !type.IsInterface
    select new
    {
        Services = type.GetInterfaces(),
        Implementation = type
    };

var lifeStyles = new Dictionary<Type, Lifestyle>()
{
    {typeof(CachedUserLookupService),Lifestyle.Singleton},
    {typeof(CachedTeamService),Lifestyle.Singleton}
};

List<Type> cacheableComponents = new List<Type>();
foreach (var reg in serviceRegistrations)
{
    foreach (var service in reg.Services)
    {
        Lifestyle lifeStyle;
        if (lifeStyles.TryGetValue(reg.Implementation, out lifeStyle) == false)
        {
            lifeStyle = Lifestyle.Singleton;
        }

        if (typeof(ICanRefreshCache) == service)
        {
            cacheableComponents.Add(reg.Implementation);
            continue;
        }

        container.Register(service, reg.Implementation, lifeStyle);
    }
}

container.RegisterAll(typeof(ICanRefreshCache), cacheableComponents);
container.RegisterManyForOpenGeneric(typeof(IEventHandler),
(closedServiceType,实现)=>
{
registeral(closedServiceType,实现);
},
应用程序组件,类型(常量)。组件);
var服务注册=
从应用程序Assembly.GetExportedTypes()中输入
其中type.Name.EndsWith(“服务”)
哪里类型.IsAbstract
哪里I型接口
选择新的
{
Services=type.GetInterfaces(),
实现=类型
};
var lifeStyles=新字典()
{
{typeof(CachedUserLookupService),lifesture.Singleton},
{typeof(CachedTeamService),lifesture.Singleton}
};
List cacheableComponents=新列表();
foreach(服务注册中的var reg)
{
foreach(注册服务中的var服务)
{
生活方式;
if(lifeStyles.TryGetValue(reg.Implementation,out lifeStyle)==false)
{
生活方式=生活方式。单身;
}
if(类型(缓存)=服务)
{
cacheableComponents.Add(注册实现);
继续;
}
容器注册(服务、注册实施、生活方式);
}
}
container.RegisterAll(typeof(ICanRefreshCache),cacheableComponents);
我想在系统启动时使用ICanRefreshCache->refresh方法刷新所有缓存,因此我调用:

步骤1:

container.GetAllInstances<ICanRefreshCache>().Each(c=>c.Refresh());
container.GetAllInstances().Each(c=>c.Refresh());
步骤2:

在我随时调用
IEventHandler
或任何其他接口类型其属于CachedUserLookupService(或CachedTeamService)之后,返回的实例与步骤1实例不同,因此此注册对我没有帮助

我需要简单的注入器注册,以提供以下呼叫

// must return Singleton CachedUserLookupService + other 
// IEventHandler<UserNameChanged> implementations
container.GetAllInstances<IEventHandler<UserNameChanged>>(); 

// must return Singleton CachedTeamService + other 
// IEventHandler<TeamCreated> implementations
container.GetAllInstances<IEventHandler<TeamCreated>>();  

// must return Singleton CachedUserLookupService
container.GetInstance<IUserLookupService>();

// must return Singleton CachedTeamService
container.GetInstance<ITeamService>();

// must return Singleton CachedUserLookupService + Singleton CachedTeamService
container.GetAllInstances<ICanRefreshCache>(); 
//必须返回Singleton CachedUserLookupService+其他
//IEventHandler实现
container.GetAllInstances();
//必须返回Singleton CachedTeamService+其他
//IEventHandler实现
container.GetAllInstances();
//必须返回Singleton CachedUserLookupService
container.GetInstance();
//必须返回Singleton CachedTeamService
container.GetInstance();
//必须返回Singleton CachedUserLookupService+Singleton CachedTeamService
container.GetAllInstances();

我使用下面的注册解决了我的问题,但我认为还有另一种方法

List<Registration> cacheableComponents = new List<Registration>();
foreach (var reg in serviceRegistrations)
{
     Lifestyle lifeStyle;
     if (lifeStyles.TryGetValue(reg.Implementation, out lifeStyle) == false)
     {
             lifeStyle = Lifestyle.Singleton;
     }

     Registration registration = null;
     if (lifeStyle == Lifestyle.Singleton)
     {
         registration = Lifestyle.Singleton.CreateRegistration(reg.Implementation, container);
     }
     else
     {
         registration = Lifestyle.Transient.CreateRegistration(reg.Implementation, container);
     }

     foreach (var service in reg.Services)
     {
       if (typeof(ICanRefreshCache) == service)
         {
             cacheableComponents.Add(registration);
             continue;
         }

          container.AddRegistration(service,registration);
     }
}
container.RegisterAll(typeof(ICanRefreshCache), cacheableComponents);
List cacheableComponents=new List();
foreach(服务注册中的var reg)
{
生活方式;
if(lifeStyles.TryGetValue(reg.Implementation,out lifeStyle)==false)
{
生活方式=生活方式。单身;
}
注册=空;
如果(生活方式==生活方式.单身)
{
registration=Lifestyle.Singleton.CreateRegistration(注册实现,容器);
}
其他的
{
注册=lifety.Transient.CreateRegistration(注册实现,容器);
}
foreach(注册服务中的var服务)
{
if(类型(缓存)=服务)
{
可缓存组件。添加(注册);
继续;
}
集装箱登记(服务、登记);
}
}
container.RegisterAll(typeof(ICanRefreshCache),cacheableComponents);

注意:此答案中的信息已过时。在Simple Injector v4中,情况发生了很大的变化

如果我理解正确,您有一个实现多个接口的组件,并且希望每个注册映射到该组件的同一个实例。因此,无论您是解析
ITeamService
icanfreshCache
还是
IEventHandler
,您都希望获得与
CachedTeamService
相同的实例

在Simple Injector中执行此操作的一般方法是手动创建
注册
实例,并为每个接口注册它,如下所示:

container.RegisterSingle<ICanRefreshCache, CanRefreshCacheComposite>();

// To make sure all all ICanRefreshCache implementations that are part of
// a collection are known to the container, call Verify() when you're done
// registering.
container.Verify();
var注册=
生活方式。单身。创建注册(容器);
container.AddRegistration(typeof(ITeamService),registration);
container.AddRegistration(typeof(ICanRefreshCache),registration);
容器。添加注册(类型(IEventHandler),注册);
这是可以解释的

但是,您的情况有点复杂,因为您将使用
RegisterManyForOpenGeneric
的批注册与普通注册混合使用。因此,您应该抑制该y的
IEventHandler
的批注册