Try our conversational search powered by Generative AI!

Removing concrete instance from IOC


Hi, need some help,

How do i remove this internal class when it is registred like this in EPiServer.Cms.Shell.UI.dll

  [ServiceConfiguration(typeof (INotificationFormatter))]
  internal class ApprovalHtmlEmailFormatter

There is no room for two, and i'd like to use mine... =) Since it is internal it is not visible in my code...

Any help appreciated.


Sep 08, 2017 17:01

Add interceptor around this and "silence" original one. Had exactly the same issue with epi forms view external resource provider.

Sep 08, 2017 17:52

You can always eject all current registered instances, then register yours. 

Sep 08, 2017 19:18

it might work in cases when you really want to dominate. there are also cases when you need to suppress that one particular instance (shut it off) but leave rest as-is. and in most cases you don't know who else is there ;)

Sep 08, 2017 20:33

Yes, but Gosso wanted to show who is the boss (tip: he is)

Sep 09, 2017 1:23

yes, thanks, 


//addin mine
context.StructureMap().Configure(ce =>

works, but i will look for finding the explicit concrete class, so i don't remove all other INoficationFormatter out there.

Bellow is not working though

 context.StructureMap().Model.EjectAndRemovePluginTypes(type => type.Namespace != null && 
            type.Namespace.Equals("EPiServer.Cms.Shell.UI.Approvals.Notifications") &&
Sep 09, 2017 10:10

Aaaand still don't you want to try intercept? ;))

Sep 09, 2017 11:44

having no luck here 

Tried Intercept...

            context.StructureMap().Configure(container =>
                container.For<INotificationFormatter>().DecorateAllWith(instance =>
                    proxyGenerator.CreateInterfaceProxyWithTargetInterface(instance, new RemoveDefaultApprovalFormatterInterceptor()));

But it is NOT hooking up on specific class, just other INotificationFormatters

DEFAULT IoC PuginType and ConcreteType is "EPiServer.Cms.Shell.UI.Approvals.Notifications.ApprovalHtmlEmailFormatter,EPiServer.Cms.Shell.UI, Version=, Culture=neutral, PublicKeyToken=8fe83dea738b45b7" SCOPE: StructureMap.Pipeline.SingletonLifecycle

When i remove the type with for example context.StructureMap().Model.EjectAndRemove(t.PluginType); the SCOPE changes to Transient (meaning it reinitiated on every call)

Removing permanentaly seems not possible?...

Any Idea how to intercept without having the concrete class since it is internal?


Sep 11, 2017 14:32

you can get to work this with code below:

public class EPiServerFormsConfigurationModule : IConfigurableModule
    public void Initialize(InitializationEngine context) { }
    public void Uninitialize(InitializationEngine context) { }
    public void ConfigureContainer(ServiceConfigurationContext context)
        context.Services.Intercept<INotificationFormatter>((locator, service) => new FixedApprovalHtmlEmailFormatter(service));

public class FixedApprovalHtmlEmailFormatter : INotificationFormatter
    private readonly INotificationFormatter _inner;
    public FixedApprovalHtmlEmailFormatter(INotificationFormatter inner)
        _inner = inner;
    public Task<IEnumerable<FormatterNotificationMessage>> FormatMessagesAsync(IEnumerable<FormatterNotificationMessage> notifications,
                                                                               string recipient,
                                                                               NotificationFormat format,
                                                                               string channelName)
        return _inner.FormatMessagesAsync(notifications, recipient, format, channelName);
    public IEnumerable<string> SupportedChannelNames => new[] { "test" };

in ideal case I would use `locator.GetInstance<INotificationFormatter>()` in `Intercept()` method, but then you will get circular dependencies and blow up from structuremap.

Sep 11, 2017 15:29

and forgot to mention that `DependencyResolverInitialization` module is my own module where I set dependency resolvers to Mvc and WebApi (created out of epi's structuremap container), but I guess you don't need explicitly chain to that phase of the initialization pipeline.

Sep 11, 2017 15:31

thx, valdis, your code illustrates it and works in "INotificationFormatter", but no luck because when i run context.StructureMap().WhatDoIHave(); the object "ApprovalHtmlEmailFormatter" is not attached to "INotificationFormatter". It is attached to it self concret class ApprovalHtmlEmailFormatter. Even if it is an INotificationFormatter.

So the question how do i "attach" to ApprovalHtmlEmailFormatter when it is not accessable...

Sep 11, 2017 16:17

Interceptors are generic concept applied to all classes. That's why you have _inner field. The only way to check which formatter was passed in is to use `GetType()` and then compare it's name in stringly typed way. There is no compile time access for you to that class.

Sep 11, 2017 16:19

I get the concept, thats cool. The problem is how to configure the object, since plugintype is not INoficationFormatter in Container, it is "ApprovalHtmlEmailFormatter", but since it is internal class, you cant ce.Intercept<ApprovalHtmlEmailFormatter>.... 

Sep 12, 2017 8:30

really? but what episerver is asking from container when it needs to format? `INoficationFormatter` or `ApprovalHtmlEmailFormatter`?

Sep 12, 2017 8:38

ApprovalHtmlEmailFormatter, anyhow, it shouldn't be this hard to either turn of default email, or brand the email, i will contact the support and give them this feedback. 

Sep 12, 2017 8:50

can you give me hint about code location thatš doing this?

Sep 12, 2017 8:59

You can check with devtools IOC, search for ApprovalHtmlEmailFormatter. 

the namespace is EPiServer.Cms.Shell.UI.Approvals.Notifications in EPiServer.Cms.Shell.UI.dll


namespace EPiServer.Cms.Shell.UI.Approvals.Notifications
  [ServiceConfiguration(typeof (INotificationFormatter), Lifecycle = ServiceInstanceScope.Singleton)]
  internal class ApprovalHtmlEmailFormatter : HtmlEmailFormatterBase, INotificationFormatter
    private readonly ApprovalEmailService _approvalEmailService;

    public IEnumerable<string> SupportedChannelNames
        return (IEnumerable<string>) new string[1]



Sep 12, 2017 9:09

ok, that's declaration. but where and how this is used later on? who and how is asking for an isntance of formatter?

Sep 12, 2017 9:11

okej, here is where the DI magic begins (param IEnumerable<INotificationFormatter> formatters)

public DefaultNotificationDispatcher(INotificationUserRepository userRepository, INotificationRepository repository, IEnumerable<INotificationFormatter> formatters, IEnumerable<INotificationProvider> providers)
      this._repository = repository;
      this._formatters = formatters ?? Enumerable.Empty<INotificationFormatter>();
      this._providers = providers ?? Enumerable.Empty<INotificationProvider>();
      this._userRepository = userRepository;

more code

internal INotificationFormatter GetFormatter(string channelName)
      List<INotificationFormatter> list = this._formatters.Where<INotificationFormatter>((Func<INotificationFormatter, bool>) (x => x.SupportedChannelNames.Contains<string>(channelName))).ToList<INotificationFormatter>();
      if (list.Count > 1)
        DefaultNotificationDispatcher.Logger.Warning("Multiple Formatters found for Channel(\"{0}\")", new object[1]
          (object) (channelName ?? "")
        return (INotificationFormatter) null;
      if (list.Count >= 1)
        return list.Single<INotificationFormatter>();
      DefaultNotificationDispatcher.Logger.Warning("No Formatter found for Channel(\"{0}\")", new object[1]
        (object) (channelName ?? "")
      return (INotificationFormatter) null;

"Multiple Formatters found for Channel (epi-approvals)" is the one i want to get around. 

Edited, Sep 12, 2017 9:24

hmm.. interesting. interceptors should not be as separate registrations in the IoC registry. You should still see just those that were implicitly registered (via attributes) or explicitly (via registries or directly). those are more for composition pipeline for structuremap itself. when you ask a `IEnumerable<Fromatters>` in let's say start page controller - do you see your interceptor formatter as another list item there?

Sep 12, 2017 9:51

oooh, when i run it in a controller (i see three FixedEmailFormatter) also see that it is another type (EPiServer.Cms.Shell.UI.Approvals.Notifications.ApprovalNotificationFormatter not ApprovalHtmlEmailFormatter), so thats why, been stearing at wrong class, the strange thing is that when i reflect, it not there.

Anyhow, that explains it, thanks Valdis, i'll see if this is something i go further with. 

Sep 12, 2017 10:34
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.