@@ -225,6 +225,125 @@ public void DecorateProvidedInstanceActivatorWithPropertyInjection()
225225 Assert . True ( service . NestedServiceIsNotNull ( ) ) ;
226226 }
227227
228+ // Issue 1459: A decorator constructor may take a dependency typed as a more
229+ // derived service than the one being decorated. The decorated instance must
230+ // not be force-injected into that parameter; it should be resolved normally.
231+ private interface IBase
232+ {
233+ }
234+
235+ private interface IDerived : IBase
236+ {
237+ }
238+
239+ private class BaseImpl : IBase
240+ {
241+ }
242+
243+ private class DerivedImpl : IDerived
244+ {
245+ }
246+
247+ private class DerivedDependencyDecorator : IBase
248+ {
249+ public DerivedDependencyDecorator ( IDerived derived , IBase decorated )
250+ {
251+ Derived = derived ;
252+ Decorated = decorated ;
253+ }
254+
255+ public IDerived Derived
256+ {
257+ get ;
258+ }
259+
260+ public IBase Decorated
261+ {
262+ get ;
263+ }
264+ }
265+
266+ private class BaseDecorator : IBase
267+ {
268+ public BaseDecorator ( IBase decorated )
269+ {
270+ Decorated = decorated ;
271+ }
272+
273+ public IBase Decorated
274+ {
275+ get ;
276+ }
277+ }
278+
279+ [ Fact ]
280+ public void DecoratorWithMoreDerivedServiceDependencyResolvesDependencyNormally ( )
281+ {
282+ // Issue 1459: The decorated service (IBase) should be supplied to the
283+ // "Decorated" parameter, while the more-derived "Derived" (IDerived)
284+ // parameter must be resolved from the container rather than receiving
285+ // the decorated IBase instance (which is not an IDerived).
286+ var builder = new ContainerBuilder ( ) ;
287+ builder . RegisterType < BaseImpl > ( ) . As < IBase > ( ) ;
288+ builder . RegisterType < DerivedImpl > ( ) . As < IDerived > ( ) ;
289+ builder . RegisterDecorator < DerivedDependencyDecorator , IBase > ( ) ;
290+
291+ var container = builder . Build ( ) ;
292+
293+ var resolved = container . Resolve < IBase > ( ) ;
294+
295+ var decorator = Assert . IsType < DerivedDependencyDecorator > ( resolved ) ;
296+ Assert . IsType < BaseImpl > ( decorator . Decorated ) ;
297+ Assert . IsType < DerivedImpl > ( decorator . Derived ) ;
298+ }
299+
300+ [ Fact ]
301+ public void DecoratorWithMoreDerivedServiceDependencyResolvesDependencyNormallyInChain ( )
302+ {
303+ // Issue 1459: When decorators are chained, the decorated instance seen by
304+ // the outer decorator is the inner decorator's output (via
305+ // DecoratorContext.UpdateContext), which is an IBase but not an IDerived.
306+ // The outer decorator's more-derived "Derived" (IDerived) parameter must
307+ // still be resolved from the container rather than receiving that chained
308+ // instance, while "Decorated" receives the inner decorator.
309+ var builder = new ContainerBuilder ( ) ;
310+ builder . RegisterType < BaseImpl > ( ) . As < IBase > ( ) ;
311+ builder . RegisterType < DerivedImpl > ( ) . As < IDerived > ( ) ;
312+
313+ // Registered first => innermost decorator.
314+ builder . RegisterDecorator < BaseDecorator , IBase > ( ) ;
315+ builder . RegisterDecorator < DerivedDependencyDecorator , IBase > ( ) ;
316+
317+ var container = builder . Build ( ) ;
318+
319+ var resolved = container . Resolve < IBase > ( ) ;
320+
321+ var outer = Assert . IsType < DerivedDependencyDecorator > ( resolved ) ;
322+ Assert . IsType < DerivedImpl > ( outer . Derived ) ;
323+
324+ var inner = Assert . IsType < BaseDecorator > ( outer . Decorated ) ;
325+ Assert . IsType < BaseImpl > ( inner . Decorated ) ;
326+ }
327+
328+ [ Fact ]
329+ public void DecoratorWithUnregisteredMoreDerivedServiceDependencyThrowsResolutionException ( )
330+ {
331+ // Issue 1459: When the more-derived "Derived" (IDerived) parameter is not
332+ // registered, the parameter falls through to normal autowiring, which
333+ // cannot satisfy it. The result should be a clean DependencyResolutionException
334+ // rather than the previous InvalidCastException from force-injecting the
335+ // decorated instance.
336+ var builder = new ContainerBuilder ( ) ;
337+ builder . RegisterType < BaseImpl > ( ) . As < IBase > ( ) ;
338+
339+ // IDerived is intentionally not registered.
340+ builder . RegisterDecorator < DerivedDependencyDecorator , IBase > ( ) ;
341+
342+ var container = builder . Build ( ) ;
343+
344+ Assert . Throws < DependencyResolutionException > ( ( ) => container . Resolve < IBase > ( ) ) ;
345+ }
346+
228347 private abstract class Decorator : IDecoratedService
229348 {
230349 protected Decorator ( IDecoratedService decorated )
0 commit comments