标签: simple-injector

生产代码中的简单注入器验证()

调用container.Verify()生产代码是最佳做法吗?我想要搬到:

#IF Debug
    container.Verify();
#ENDIF
Run Code Online (Sandbox Code Playgroud)

我没有任何真正的理由做出改变,只是好奇一般共识/最佳实践是什么.

c# simple-injector

6
推荐指数
1
解决办法
1879
查看次数

SimpleInjector如何为单个通用实现注册多个开放通用接口

我正在尝试使用SimpleInjector作为IOC容器,到目前为止我对此非常满意.但是现在我遇到了一个我无法解决的问题.我搜索了SO和文档,但似乎还没有回答.我已经看过SimpleInjector的howto doc但是它没有涵盖开放的通用接口.

我有两个这样的通用接口:

public interface IEventPublisher<TEvent>
{
   void Publish(TEvent Event);
}
public interface IEventSubscriber<TEvent>
{
    void Subscribe(Action<TEvent> CallBack);
}
Run Code Online (Sandbox Code Playgroud)

这两个开放的通用实现:

class EventMediator<T> : IEventPublisher<T>, IEventSubscriber<T>
{
    List<Action<T>> Subscriptions = new List<Action<T>>();

    public void Publish(T Event)
    {
        foreach (var Subscription in this.Subscriptions)
            Subscription.Invoke(Event);
    }

    public void Subscribe(Action<T> CallBack)
    {
        this.Subscriptions.Add(CallBack);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我正在设置SimpleInjector,如下所示:

this.Container = new SimpleInjector.Container();
this.Container.RegisterOpenGeneric(typeof(IEventPublisher<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.RegisterOpenGeneric(typeof(IEventSubscriber<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.Verify();
Run Code Online (Sandbox Code Playgroud)

我想要存档的是:在要求IEventPublisher或IEventSubscriber时,我想获得完全相同的实例.此外,此实例应为任何T的单例.

我用这些线测试了这个:

class DummyEvent {}

var p = this.Container.GetInstance<IEventPublisher<DummyEvent>>();
var s = this.Container.GetInstance<IEventSubscriber<DummyEvent>>();
var areSame …
Run Code Online (Sandbox Code Playgroud)

c# generics open-generics simple-injector

6
推荐指数
1
解决办法
809
查看次数

Web api控制器的简单注射器生活方式警告

我正在关注简单的注入器文档站点上的文档.

https://simpleinjector.readthedocs.org/en/latest/diagnostics.html

var container = new Container();
container.RegisterWebApiControllers(config);
container.Verify();

var results = Analyzer.Analyze(container);

results.Should()
  .HaveCount(0, String.Join( Environment.NewLine, results.Select(x => x.Description)));
Run Code Online (Sandbox Code Playgroud)

但是,当我运行我的测试时,我收到以下错误

Xunit.Sdk.AssertException: 
Expected collection to contain 0 item(s) because 
MyController is registered as transient, but implements IDisposable., 
but found 1.
Run Code Online (Sandbox Code Playgroud)

我不知道如何设置控制器的范围,因为该方法container.RegisterWebApiControllers(config)是webapi包的一部分,并且没有任何重载.如何根据网络请求设置这些内容?在其他地方,我会这样做,container.Register<IPinger, Pinger>(lifestyle);但似乎我应该使用打包的帮助方法


添加此行以过滤掉不需要的误报

results = results.Where(x => 
   !(x.ServiceType.BaseType == typeof (ApiController) && 
     x.Description.Contains("IDisposable"))
    ).ToArray();
Run Code Online (Sandbox Code Playgroud)

c# ioc-container simple-injector

6
推荐指数
1
解决办法
3618
查看次数

如何进行懒惰注射的异步初始化

假设我们想要注入一个昂贵的对象(假设它从数据库初始化),所以我们通常会使用某种工厂或Lazy<T>.但是,如果我们将此对象注入使用异步操作方法的MVC或WebApi控制器,我们不希望在初始化Lazy对象时在昂贵的I/O操作上阻止这些方法,这会破坏目的使用异步.

当然,我可以创建一个异步的"initlize"方法,但这违反了许多原则.

以惰性和异步方式访问和初始化注入对象的最佳选择是什么?

c# asynchronous dependency-injection simple-injector

6
推荐指数
2
解决办法
1939
查看次数

具有多个有界DbContexts的简单注入器 - 异常"IDbContext已经注册"

我正在尝试切换到Simple Injector Dependency Injection框架,因为我对它的速度印象深刻.

 private static void RegisterServices(Container container)
 {
     container.RegisterPerWebRequest<IDbContext, DbContext1>();
     ////container.RegisterPerWebRequest<IDbContext, DbContext2>();    
     container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
     container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
Run Code Online (Sandbox Code Playgroud)

其中DbContext1和DbContext2继承自BaseDbContext类

public class BaseDbContext<TContext> : DbContext, IDbContext where TContext : DbContext
Run Code Online (Sandbox Code Playgroud)

它实现了一个相当简单的IDbContext接口(就像在SO上提供的许多接口),例如:

public interface IDbContext
{
    IQueryable<TEntity> Find<TEntity>() where TEntity : class;
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
    int SaveChanges();
    void Dispose();
}
Run Code Online (Sandbox Code Playgroud)

如果我只使用一个DbContext类,它可以正常工作 - 存储库被注入,数据被拉出等.

但是,我还想在每个中使用带有少量DbSet的有界上下文(使用DDD有界上下文缩小EF模型),因为我的Code-First DbContext将包含数百个类

private static void RegisterServices(Container container)
 {
     container.RegisterPerWebRequest<IDbContext, DbContext1>();
     container.RegisterPerWebRequest<IDbContext, DbContext2>();

     container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
     container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
Run Code Online (Sandbox Code Playgroud)

然后我得到一个例外:

System.InvalidOperationException未由用户代码处理HResult = -2146233079消息=类型IDbContext已经注册,并且容器当前未配置为允许覆盖注册.要允许覆盖当前注册,请将Container.Options.AllowOverridingRegistrations设置为true.Source = …

entity-framework dependency-injection simple-injector

5
推荐指数
1
解决办法
2733
查看次数

使用Simple Injector进行方法级别的属性拦截

使用Unity,我可以快速添加基于属性的拦截

public sealed class MyCacheAttribute : HandlerAttribute, ICallHandler
{
   public override ICallHandler CreateHandler(IUnityContainer container)
   {
        return this;
   }

   public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
   {
      // grab from cache if I have it, otherwise call the intended method call..
   }
}
Run Code Online (Sandbox Code Playgroud)

然后我这样注册Unity:

container.RegisterType<IPlanRepository, PlanRepository>(
    new ContainerControlledLifetimeManager(),
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());
Run Code Online (Sandbox Code Playgroud)

在我的存储库代码中,我可以选择性地装饰要缓存的某些方法(具有可以为每个方法单独定制的属性值):

    [MyCache( Minutes = 5, CacheType = CacheType.Memory, Order = 100)]
    public virtual PlanInfo GetPlan(int id)
    {
        // call data store to get this plan;
    }
Run Code Online (Sandbox Code Playgroud)

我在Simple Injector中探索类似的方法.从我读取和搜索的内容看起来只有接口/类型级别拦截可用.但我希望能够选择使用这种属性控制的拦截行为来装饰各个方法.有什么建议吗? …

c# dependency-injection ioc-container simple-injector

5
推荐指数
1
解决办法
2470
查看次数

simpleinjector 3.0不支持RegisterManyForOpenGeneric

所以我决定将我的simpleinjector版本升级到3.0,突然间我收到一条消息:

'SimpleInjector.Extensions.OpenGenericBatchRegistrationExtensions.RegisterManyForOpenGeneric(SimpleInjector.Container,System.Type,params System.Reflection.Assembly [])'已过时:'此扩展方法已被删除.请改用Container.Register(Type,IEnumerable).

文档中仍然有这个方法:

http://simpleinjector.readthedocs.org/en/latest/advanced.html

所以我很好奇,有什么替代方案:

container.RegisterManyForOpenGeneric(typeof(IEventHandler<>),
                                     container.RegisterAll,
                                     typeof(IEventHandler<>).Assembly);
Run Code Online (Sandbox Code Playgroud)

c# simple-injector

5
推荐指数
1
解决办法
1031
查看次数

使用简单的注入器和Umbraco控制器

我正在尝试将依赖项注入到一个控制器中,该控制器继承自Umbraco的RenderMvcController并获取错误

无法注册RenderMvcController类型,也无法进行隐式注册.为了能够创建RenderMvcController的容器,它应该只有一个公共构造函数:它有3个.有关更多信息,请参阅https://simpleinjector.org/one-constructor.

下面是我连接DI的代码

        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

        InitializeContainer(container);

        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

        container.Verify();

        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));



    private static void InitializeContainer(Container container)
    {
        container.Register<ICacheProvider, CacheProvider>(Lifestyle.Transient);
        container.Register<ICacheService, CacheService>(Lifestyle.Transient);
    }
Run Code Online (Sandbox Code Playgroud)

这是接收依赖的类的一个例子,它继承自我写的基类

public class NewsroomController : BaseRenderMvcController
{
    public NewsroomController(ICacheService cacheService) : base(cacheService) { }
Run Code Online (Sandbox Code Playgroud)

基类扩展了RenderMvcController,它是一个Umbraco控制器

public class BaseRenderMvcController : RenderMvcController
{
    public ICacheService CacheService { get; set; }
    public BaseRenderMvcController(ICacheService cacheService)
    {
        CacheService = cacheService;
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,基础Umbraco控制器实际上有3个不同的构造函数

public class RenderMvcController : UmbracoController, IRenderMvcController, IRenderController, IController
{
    public RenderMvcController();
    public …
Run Code Online (Sandbox Code Playgroud)

c# dependency-injection umbraco simple-injector

5
推荐指数
1
解决办法
967
查看次数

在简单注入器中注册部分开放的泛型

我正在尝试注册一个开放的通用接口IService<T1>并使用以下部分开放的实现类来解决它Service<T0, T1>。在这种情况下,T0是固定的,并且T1fromServiceIService是相同的。

理想情况下,它看起来像这样:

container.Register<IService<>, Service<ExplicitType,>>(Lifestyle.Singleton);

但这是不正确的c#。

我的问题是:

  • 那有意义吗 ?或者,还有更好的方法。Service<ExplicitType,>如果可能的话,我想避免上课。
  • 有可能吗?

我发现优秀的文档对这个问题没有帮助。

c# generics dependency-injection simple-injector

5
推荐指数
1
解决办法
930
查看次数

简单注入器-使用一个自定义参数注册服务

我尝试使用自定义参数“服务器”注册通信服务。但我想自动解决ILogger依赖关系,而不要两次设置此依赖关系。

最好的方法是什么?

SimpleInjector寄存器

var diContainer = new Container();
diContainer.Register<ILogger, DefaultLogger>();
//Good
diContainer.Register<ICommunicationService>(
    () => new CommunicationService("server1"), 
    Lifestyle.Singleton);
//Bad
diContainer.Register<ICommunicationService>(
    () => new CommunicationService(new DefaultLogger(), "server1"),
    Lifestyle.Singleton);
Run Code Online (Sandbox Code Playgroud)

CommunicationService类别

public class CommunicationService : ICommunicationService
{
    public CommunicationService(ILogger logger, string server)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

更新2017-11-27

@Steven我要运行两个CommunicationService具有不同配置的实例。在我的示例中server1和server2。

var container = new Container();
container.Register<ILogger, DefaultLogger>();
container.RegisterSingleton(new CommunicationServiceConfig { Server = "server1" });
container.RegisterSingleton(new CommunicationServiceConfig { Server = "server2" });

diContainer.Register<ICommunicationService, CommunicationService>(Lifestyle.Singleton);
diContainer.Register<ICommunicationService, CommunicationService>(Lifestyle.Singleton);
Run Code Online (Sandbox Code Playgroud)

c# dependency-injection ioc-container simple-injector

5
推荐指数
1
解决办法
922
查看次数