Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace default/existing services by custom implementations #983

Closed
tobyee opened this issue Apr 14, 2016 · 8 comments
Closed

Replace default/existing services by custom implementations #983

tobyee opened this issue Apr 14, 2016 · 8 comments
Assignees
Milestone

Comments

@tobyee
Copy link

tobyee commented Apr 14, 2016

Sometimes, I want to replace the implement for specific interface,but it seems that IocManager.Register only register the implemented class for the first register call.
Anyway I finally found a way to do that.

// first register
IocManager.Register<IFoo, FooImpl1>();
IocManager.Resolve<IFoo>(); // == FooImpl1
// try to replace
IocManager.Register<IFoo, FooImpl2>();
IocManager.Resolve<IFoo>(); // == FooImpl1
// try another way to replace
IocManager.IocContainer.Register(Component
    .For<IFoo>()
    .ImplementedBy<FooImpl2>()
    .IsDefault());
IocManager.Resolve<IFoo>(); // == FooImpl2

But, it's not convenient.
Can IIconManager provide some method like Replace<>?

@tobyee tobyee changed the title How can I replace an implemented class that registered before in IIocManager? How can I replace an implemented class that registered in IIocManager before? Apr 14, 2016
@hikalkan
Copy link
Member

Registrations are done in module's Initialize. You can register in PreInitialize to override it. But I will consider to add some 'replace' logic to simplify it.
Thanks.

@hikalkan hikalkan added this to the ABP v1.0.0 milestone Apr 15, 2016
@tobyee
Copy link
Author

tobyee commented Apr 15, 2016

@tobyee tobyee closed this as completed Apr 15, 2016
@tobyee tobyee reopened this Apr 15, 2016
@hikalkan hikalkan modified the milestones: ABP v0.9.0, ABP v1.0.0 May 5, 2016
@hikalkan
Copy link
Member

hikalkan commented May 5, 2016

Hi,

I added ReplaceService method to startup configuration. For example, we can use such a code to replace IConnectionStringResolver with our custom implementation DbPerTenantConnectionStringResolver:

Configuration.ReplaceService(typeof(IConnectionStringResolver), () =>
{
    IocManager.Register<IConnectionStringResolver, DbPerTenantConnectionStringResolver>(DependencyLifeStyle.Transient);
});

We should write this in PreInitialize event of our module.

Same service can be replaced/overrided multiple times. Last one will be valid. If Module B depends on Module A and both overrides same service, then the one overrided by module B will be valid sinde Modul B's PreInitialize runs after Module A.

I made second parameter an action, instead of simply a type. Because, there may be complex replace scenarios. Example:

Configuration.ReplaceService(typeof(IConnectionStringResolver), () =>
{
    IocManager.IocContainer.Register(
        Component.For<IConnectionStringResolver, IDbPerTenantConnectionStringResolver>()
            .ImplementedBy<DbPerTenantConnectionStringResolver>()
            .LifestyleTransient()
        );
});

This is a real code from module zero that replaces IConnectionStringResolver (https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero.EntityFramework/Zero/EntityFramework/AbpZeroEntityFrameworkModule.cs#L18). Notice that it registers DbPerTenantConnectionStringResolver for two interfaces (IConnectionStringResolver, IDbPerTenantConnectionStringResolver). Also, you may need to use more advanced methods of Castle Windsor here.

@hikalkan hikalkan changed the title How can I replace an implemented class that registered in IIocManager before? Replace default/existing services by custom implementations May 5, 2016
@natiki
Copy link
Contributor

natiki commented May 6, 2016

When you update the doco could we also have an example to replace the ILogger interface with say a Serilog.ILogger for instance? ;-)

@hikalkan
Copy link
Member

hikalkan commented May 6, 2016

Replacing ILogger is a bit different. Because, it's registered before ABP initialized. But it's already registered in template, in global.asax file. You can just remove and register serilog. I did write it before (you can search for it).

@hikalkan hikalkan self-assigned this May 6, 2016
@hikalkan
Copy link
Member

hikalkan commented May 6, 2016

I added shortcut extension methods. Example:

Configuration.ReplaceService<IServiceType, MyImplementation>(DependencyLifeStyle.Transient);

@brunobertechini
Copy link

Hello @hikalkan

I've reached a situation where I create a custom module with a custom configuration. I would like to allow applications using my custom module to be able to set some property and only if this property is true, I will replace the service.

Since App depends on MyCustomModule, I can't rely on PreInitialize to use ReplaceService.

AppModule1 - depends on MyCustomModule
AppModule1 configure a given setting:

public override void PreInitialize()
{
    Configuration.Modules.MyCustomModule().SettingAEnabled = true;
}

CustomModule should use this setting in order to replace a service. This is not working since it is located at Initialize rather than PreInitialize.

public override void Initialize()
{
    if(Configuration.Modules.MyCustomModule().SettingAEnabled)
    {
           Configuration.ReplaceService(typeof(IAbpSession), () =>
                {
                    IocManager.Register<IAbpSession, MyCustomModuleSession>();
                });
    }
}

Any thoughts?

Should I use other approach ?

I would like to replace IAbpSession for example if a dependant module enable specific setting.

Thanks a lot

@hikalkan
Copy link
Member

There is a possibility to configure MyCustomModule by AppModule1 before PreInitialize. Please check this: http://www.aspnetboilerplate.com/Pages/Documents/Module-System#DocCustomModule

You can inject MyCustomModule into AppModule1's constructor and set a boolean property of it in the constructor.

KenProDev pushed a commit to KenProDev/aspnetboilerplate that referenced this issue Jan 17, 2017
KenProDev pushed a commit to KenProDev/aspnetboilerplate that referenced this issue Jan 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants