调用container.Verify()生产代码是最佳做法吗?我想要搬到:
#IF Debug
container.Verify();
#ENDIF
Run Code Online (Sandbox Code Playgroud)
我没有任何真正的理由做出改变,只是好奇一般共识/最佳实践是什么.
我正在尝试使用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) 我正在关注简单的注入器文档站点上的文档.
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) 假设我们想要注入一个昂贵的对象(假设它从数据库初始化),所以我们通常会使用某种工厂或Lazy<T>.但是,如果我们将此对象注入使用异步操作方法的MVC或WebApi控制器,我们不希望在初始化Lazy对象时在昂贵的I/O操作上阻止这些方法,这会破坏目的使用异步.
当然,我可以创建一个异步的"initlize"方法,但这违反了许多原则.
以惰性和异步方式访问和初始化注入对象的最佳选择是什么?
我正在尝试切换到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 = …
使用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中探索类似的方法.从我读取和搜索的内容看起来只有接口/类型级别拦截可用.但我希望能够选择使用这种属性控制的拦截行为来装饰各个方法.有什么建议吗? …
所以我决定将我的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) 我正在尝试将依赖项注入到一个控制器中,该控制器继承自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) 我正在尝试注册一个开放的通用接口IService<T1>并使用以下部分开放的实现类来解决它Service<T0, T1>。在这种情况下,T0是固定的,并且T1fromService和IService是相同的。
理想情况下,它看起来像这样:
container.Register<IService<>, Service<ExplicitType,>>(Lifestyle.Singleton);
但这是不正确的c#。
我的问题是:
Service<ExplicitType,>如果可能的话,我想避免上课。我发现优秀的文档对这个问题没有帮助。
我尝试使用自定义参数“服务器”注册通信服务。但我想自动解决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)