简体   繁体   English

统一注销服务

[英]Unregister service from unity

I'm using Unity within my application. 我在应用程序中使用Unity。 For one integration test, we want to change one of the service registered to the application(because it would require some hardware). 对于一个集成测试,我们想更改向应用程序注册的一项服务(因为它需要一些硬件)。

So, I'm able to Register the new "mock" type, but I'm unable to remove the other implementation registered for this interface. 因此,我可以注册新的“模拟”类型,但是无法删除为此接口注册的其他实现。

Also to mention, currently we register a "list" of this interface(it's some kind of driver) and we would like to remove all the others instance. 另外要提到的是,当前我们在此接口(它是某种驱动程序)上注册一个“列表”,并且我们想删除所有其他实例。

Any idea how I could do this? 知道我该怎么做吗?

You can simply override the registration with either mocks, or a blank implementation. 您可以使用模拟或空白实现简单地覆盖注册。 In the case of named registrations, it will work as long as you register with the same name. 对于命名注册,只要您使用相同的名称注册,它就可以工作。 As you add a new registration, Unity will ignore the former registrations. 添加新注册时,Unity将忽略以前的注册。

In our UnitTesting projects, we currently add all the regular registrations, then in the setup we register mocks on top of them. 当前,在UnitTesting项目中,我们添加所有常规注册,然后在设置中,在它们之上注册模拟。

I'm assuming you are not using Container.IsRegistered in your tests (which is not always a valid assumption). 我假设您在测试中未使用Container.IsRegistered(这并不总是一个有效的假设)。

A similar approach to @Tipx answer is to re-register but provide an InjectionMember that will clear all of the policies associated with the type. 与@Tipx答案类似的方法是重新注册,但提供一个InjectionMember ,它将清除与该类型关联的所有策略。 This has the benefit that, since the policy configuration has been removed, Unity should work as if the types were never registered (even though they will appear in the Registrations list). 这样做的好处是,由于已删除策略配置,因此Unity应该像从未注册过的类型一样工作(即使它们将出现在“注册”列表中)。

Here's the InjectionMember ClearAllPolicies which clears the policies: 这是清除策略的InjectionMember ClearAllPolicies:

public class ClearAllPolicies : InjectionMember
{
    public override void AddPolicies(Type serviceType, Type implementationType, string name, IPolicyList policies)
    {
        var serviceTypeBuildKey = new NamedTypeBuildKey(serviceType, name);
        policies.Clear<IBuildKeyMappingPolicy>(serviceTypeBuildKey);

        var buildKey = new NamedTypeBuildKey(implementationType, name);

        policies.Clear<IBuildKeyMappingPolicy>(buildKey);
        policies.Clear<IConstructorSelectorPolicy>(buildKey);
        policies.Clear<IBuildPlanCreatorPolicy>(buildKey);
        policies.Clear<IBuildPlanPolicy>(buildKey);
        policies.Clear<IMethodSelectorPolicy>(buildKey);
        policies.Clear<IPropertySelectorPolicy>(buildKey);
        policies.Clear<ILifetimeFactoryPolicy>(buildKey);
        policies.Clear<ILifetimePolicy>(buildKey);
        policies.Clear<IBuilderPolicy>(buildKey);

        DependencyResolverTrackerPolicy.RemoveResolvers(policies, buildKey);
    }
}

Here's an example where 3 ILogger named implementations are registered and a list of ILogger s is resolved. 这是一个示例,其中注册了3个以ILogger命名的实现,并解析了ILogger的列表。 Then the polices are cleared for the loggers and a check is done to ensure that ILogger can't be resolved: 然后清除记录器的策略,并进行检查以确保无法解决ILogger

IUnityContainer container = new UnityContainer();

container.RegisterType<ILogger, MyLogger>("Logger1");
container.RegisterType<ILogger, MyLogger>("Logger2");
container.RegisterType<ILogger, MyLogger>("Logger3");

// Resolve list of all loggers
var loggers = container.Resolve<ILogger[]>();

// Remove Policies for all ILoggers using ClearAllPolicies
foreach (var registration in container.Registrations
                                      .Where(r => r.RegisteredType == typeof(ILogger)))
{
    container.RegisterType(
       registration.RegisteredType,
       registration.MappedToType, 
       registration.Name, 
       new ClearAllPolicies());
}

// Ensure that when we try to resolve an ILogger or list of ILogger's that
// an exception is thrown
Assert.Throws<ResolutionFailedException>(() => container.Resolve<ILogger>("Logger1"));
Assert.Throws<ResolutionFailedException>(() => container.Resolve<ILogger>("Logger2"));
Assert.Throws<ResolutionFailedException>(() => container.Resolve<ILogger>("Logger3"));
Assert.Throws<ResolutionFailedException>(() => container.Resolve<ILogger[]>());

Caveats & Warnings 注意事项和警告

  • Do not use this in production code -- I would only use this for testing purposes 不要在生产代码中使用它-我只会将其用于测试目的
  • It's possible that this does not capture all of the applicable policies and is not complete or does not work for every edge case (eg Interception or other esoteric scenarios) 这可能无法捕获所有适用的策略,并且可能不完整,或者不适用于每种极端情况(例如,拦截或其他深奥的场景)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM