Dependencyinjection: рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╕рдордп рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА

рдХреЛ рдирд┐рд░реНрдорд┐рдд 6 рдорд╛рд░реНрдЪ 2017  ┬╖  9рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: aspnet/DependencyInjection

рдпрд╣ рдПрдХ рд╕реБрд╡рд┐рдзрд╛ рдЕрдиреБрд░реЛрдз рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ рдпрджрд┐ рдпрд╣ рдЧрд▓рдд рдкреНрд░рд╛рд░реВрдк/рдЧрд▓рдд рд╕реНрдерд╛рди рд╣реИред

рдПрд╕реНрдкрдиреЗрдЯ/рд▓реЙрдЧрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдореИрдВ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ рдЬрд┐рд╕рдореЗрдВ рдореИрдВ рдЧреИрд░-рдЬреЗрдиреЗрд░рд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ ILogger рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рдерд╛ред

рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ ILogger рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддреЗ рд╕рдордп рд▓рдХрдбрд╝рд╣рд╛рд░реЗ рдХреЛ рд▓рдХрдбрд╝рд╣рд╛рд░реЗ рдХреЗ рд╕рдВрджреЗрд╢-рдХреНрд╖реЗрддреНрд░ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

рд╡рд░реНрддрдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:

public class UsersController : Controller
{
    private readonly ILogger _logger;

    public UsersController(ILogger<UsersController> logger)
    {
        _logger = logger;
    }
}

рдЬрд╣рд╛рдВ рдореЗрд░рд╛ рд╡рд╛рдВрдЫрд┐рдд рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рджрд┐рдЦреЗрдЧрд╛:

public UsersController(ILogger logger)
{
    _logger = logger;
}

рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рднрд╛рд╖рд╛ рдмреЗрдорд╛рдиреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ T рдХреЗ рд╕рд╛рде рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рд░реАрд╢реЗрд░реНрдкрд░ рд╕реЗ рд╕реБрдЭрд╛рд╡ рдорд┐рд▓рддреЗ рд╣реИрдВ рдХрд┐ рдореБрдЭреЗ рдЧреИрд░-рдЬреЗрдиреЗрд░рд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВред

рдЧреИрд░-рдЬреЗрдиреЗрд░рд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрд╕реНрдкрдиреЗрдЯ/рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдХреЛ рдмрддрд╛рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд▓реЙрдЧрд░ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдПред

рдореИрдВ рдЬрд┐рд╕ рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ рдЬрд┐рд╕ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдпрд╣ рди рдХреЗрд╡рд▓ рдореЗрд░реЗ рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдмрд▓реНрдХрд┐ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЬреИрд╕реЗ рдХрд┐ рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордпред

рдореИрдВ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЬреЛ рдореИрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рд╣реЛрдЧрд╛:

services.AddTransient<ILogger>(
    (s, ctx) => s.GetService<ILoggerFactory>().CreateLogger(ctx.DestinationType));

рдЬрд╣рд╛рдВ ctx.DestinationType рд╡рд╣ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЦреБрд▓реЗ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕рдЬрд╛рд╡рдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдПрдХ рд╕рдорд╛рди, рд▓реЗрдХрд┐рди рдереЛрдбрд╝реА рдЕрд▓рдЧ рд╕реБрд╡рд┐рдзрд╛ рдорд╛рдВрдЧреА рд╣реИ; рдлрд╝реИрдХреНрдЯрд░реА рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдореЗрдВ рдЕрдиреБрд░реЛрдзрд┐рдд рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдЙрджрд╛рд╣рд░рдг:

services.AddScoped(typeof(IService<>), typeof(Service<>));

// the call below is basically a way to do decoration with MS.Ext.DI...
services.AddScoped(typeof(IService<>), (provider, context) =>
{
    var typeArgument = context.RequestedType.GetGenericArguments().First();

    var decoratorType = typeof(DecoratedService<>).MakeGenericType(typeArgument);

    var decoratedInstance = /* get the decorated instance from the service provider */

    return ActivatorUtilities.CreateInstance(provider, decoratorType, decoratedInstance);
});

рдЬрд╣рд╛рдВ context.RequestedType рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЕрд░реНрдерд╛рдд provider.GetService<IService<string>>() -> typeof(IService<string>) ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдореБрдЦреНрдп рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ MS.Ext.DI рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ "рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ" рд▓рд╛рдПрдЧрд╛ред рдЕрдЪрд╛рдирдХ, рдЙрди рд╕рднреА рдХреЛ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ред

рд╕рднреА 9 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЦреБрд▓реЗ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕рдЬрд╛рд╡рдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдПрдХ рд╕рдорд╛рди, рд▓реЗрдХрд┐рди рдереЛрдбрд╝реА рдЕрд▓рдЧ рд╕реБрд╡рд┐рдзрд╛ рдорд╛рдВрдЧреА рд╣реИ; рдлрд╝реИрдХреНрдЯрд░реА рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдореЗрдВ рдЕрдиреБрд░реЛрдзрд┐рдд рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдЙрджрд╛рд╣рд░рдг:

services.AddScoped(typeof(IService<>), typeof(Service<>));

// the call below is basically a way to do decoration with MS.Ext.DI...
services.AddScoped(typeof(IService<>), (provider, context) =>
{
    var typeArgument = context.RequestedType.GetGenericArguments().First();

    var decoratorType = typeof(DecoratedService<>).MakeGenericType(typeArgument);

    var decoratedInstance = /* get the decorated instance from the service provider */

    return ActivatorUtilities.CreateInstance(provider, decoratorType, decoratedInstance);
});

рдЬрд╣рд╛рдВ context.RequestedType рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЕрд░реНрдерд╛рдд provider.GetService<IService<string>>() -> typeof(IService<string>) ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдореБрдЦреНрдп рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ MS.Ext.DI рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ "рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ" рд▓рд╛рдПрдЧрд╛ред рдЕрдЪрд╛рдирдХ, рдЙрди рд╕рднреА рдХреЛ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ред

рд╢рд╛рдпрдж рдЗрд╕реЗ рдЖрдЧреЗ рдХреА рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

LightInject рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ RegisterConstructorDependency/RegisterPropertyрдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпрд╛рдВ рдЬреЛ рдЗрдВрдЬреЗрдХреНрд╢рди рдХреА рдЬрд╛ рд░рд╣реА рдирд┐рд░реНрднрд░рддрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд "рд╕рдВрджрд░реНрдн" рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИрдВред

рдирд┐рдореНрди рдЙрджрд╛рд╣рд░рдг рдПрдХ рд▓рдХрдбрд╝рд╣рд╛рд░рд╛ рдмрдирд╛рдиреЗ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдЬреЛ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рд▓рдХрдбрд╝рд╣рд╛рд░реЗ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИ
http://www.lightinject.net/webapirequestloging/

рд╣реБрд╣ред рдореИрдВ рдЗрд╕ рдЫреЛрдЯреА рд╕реА рдмрд╛рддрдЪреАрдд рдХреЗ рдХрд╛рд░рдг рдпрд╣рд╛рдВ рдареЛрдХрд░ рдЦрд╛рдИ, рдЬреЛ рдПрдХ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдкреНрд░рд╢реНрди рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реБрдИ рдереА рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рдЙрд╕реА рд╕рд╛рдорд╛рдиреНрдп рдЪрд┐рдВрддрд╛ рдХреЗ рд╕рд╛рде рдпрд╣рд╛рдВ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдерд╛ред рдореИрдВ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ @рдЦреЗрд▓рдВрдЧ рдиреЗ рдкрд╣рд▓реЗ рдХрд╣рд╛рдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рдерд╛ред рдХреНрдпрд╛ рдпрд╣ рдПрдХ рдФрд░ рдореБрджреНрджрд╛ рд╣реИ?

рдпрджрд┐ рдпрд╣ рд╕рд╣рд╛рдпрдХ рд╣реИ, рддреЛ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдкрд░ рдореЗрд░рд╛ рдкреНрд░рд╢реНрди рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рдкреВрдЫ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдирд╣реАрдВ рдХрд┐ рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╕рд╣рд╛рдпрдХ рдХреНрдпреЛрдВ рд╣реЛрдЧреАред рдЬрдм рдЖрдк рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд░реИрдкрд░ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рддрд░реНрдХ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдХрдерд╛ рдХреА рдЖрддреНрдорд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

рдорд╛рди рд▓реЗрдВ рдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ IRepository<TModel> рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рджреЛ рд╡рд░реНрдЧ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореИрдВ рдЗрд╕рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, FreeSpirit рдФрд░ Curmudgeon ред рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдпрд╣рд╛рдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реВрдВрдЧрд╛:

public interface IRepository<TModel> where TModel: Model {
    public TModel GetById(Guid id);
    public TModel Create(TModel toCreate);
}

public class FreeSpirit : Model {
    public Guid Id { get; }
    public String Name { get; }

    public FreeSpirit(Guid id, String name) {
        this.Id = id;
        this.Name = name;
    }
}

public class Curmudgeon : Model {
    public Guid Id { get; }
    public DateTime EventTimestamp { get; }

    public Curmudgeon(Guid id, DateTime eventTimestamp) {
        this.Id = id;
        this.EventTimestamp = eventTimestamp;
    }
}

StandardRepository<TModel> рдХреЗ рдЖрдзрд╛рд░ рджреГрдврд╝рддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдорд╛рдирддреЗ рд╣реБрдП, рд╣рдо рдЗрд╕ рдХреЛрдб рдХреЛ ASP.NET рдХреЗ рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдЯреВрд▓рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ:

services.AddScoped(typeof(IRepository<>), typeof(StandardRepository<>));

рдЕрдм, рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рд░ рдмрд╛рд░ рдЬрдм рдХреЛрдИ Curmudgeon рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ рддреЛ рд╣рдо рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрд╕ рдбреЗрд▓реНрдЯрд╛ рдХреЛ рдХреБрдЫ рдСрдбрд┐рдЯ рд▓реЙрдЧ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдирд╛ред рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ [Audited] рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕реЗ Curmudgeon рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдПрдХ AuditingRepositoryWrapper<TModel> рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ:

[Audited]
public class Curmudgeon : Model {
    public Guid Id { get; }
    public DateTime EventTimestamp { get; }

    public Curmudgeon(Guid id, DateTime eventTimestamp) {
        this.Id = id;
        this.EventTimestamp = eventTimestamp;
    }
}

public class AuditingRepositoryWrapper<TModel> : IRepository<TModel> {

    private IRepository<TModel> inner { get; }
    private IAuditingService auditService { get; }

    public AuditingRepositoryWrapper(IRepository<TModel> inner, IAuditingService auditService) {
        this.inner = inner;
        this.auditService = auditService;
    }

    public TModel GetById(Guid id) {
        return this.inner.GetById(id);
    }

    public TModel Create(TModel toCreate) {
        var result = this.inner.Create(toCreate);

        this.auditService.AuditChanges(toCreate, result);

        return result;
    }

}

рдЕрдм рдкрдВрдЬреАрдХрд░рдг рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдореБрдЭреЗ рдЕрдкрдиреЗ StandardRepository<TModel> рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ AuditingRepositoryWrapper<TModel> рдХреЗ рд╕рд╛рде рд▓рдкреЗрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдпрджрд┐ рдХреЗрд╡рд▓ [Audited] рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИред context рдЪрд░ рдХреЗ @khellang рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдмрдЬрд╛рддреЗ рд╣реБрдП, рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдХрд░ рд╕рдХрддрд╛ рдерд╛:

рд╕рд╛рдорд╛рдиреНрдп, рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо:

services.AddScoped(typeof(StandardRepository<>));
services.AddScoped(typeof(IAuditingService), typeof(AuditingService));

services.AddScoped(typeof(IService<>), (provider, context) => {
    var typeArgument = context.RequestedType.GetGenericArguments().First();

    var isAudited =
        typeArgument
            .GetTypeInfo()
            .CustomAttributes
            .Any(attr => attr.AttributeType == typeof(AuditedAttribute));

    // Would need to solve the lack of closing type for the repository variable at this point.
    // (I think the best way to solve this is with a factory at this point that takes in the 'context'.)
    // See: https://github.com/invio/Invio.Extensions.DependencyInjection

    IRepository<?> repository = provider.GetRequiredService(typeof(StandardRepository<?>), typeArgument);
    if (isAudited) {
        repository = new AuditingRepositoryWrapper<?>(
            provider.GetRequiredService(repository, typeof(IAuditingService));
        );
    }

    return repository;
});

рдореЗрд░реА рдЯреАрдо рдЖрдЬ рдХреБрдЫ рдРрд╕рд╛ рдХрд░рдХреЗ рдЗрд╕ рдкрд░ рдХрд╛рдмреВ рдкрд╛ рд▓реЗрддреА рд╣реИ рдЬреЛ рдирд┐рдореНрди рдХреЗ рдЬреИрд╕рд╛ рд╣реИ:

services.AddScoped(typeof(StandardRepository<>));
services.AddScoped(typeof(IAuditingService), typeof(AuditingService));

services.AddRepository<FreeSpirit>();
services.AddRepository<Curmudgeon>();
[ ... ]

public static IServiceCollection AddRepository<TModel>(this IServiceCollection services) {
    var isAudited =
        typeof(TModel)
            .GetTypeInfo()
            .CustomAttributes
            .Any(attr => attr.AttributeType == typeof(AuditedAttribute));

    if (isAudited) {
        services.AddScoped(
            typeof(IRepository<TModel>),
            (provider) => {
                new AuditingRepositoryWrapper<TModel>(
                    provider.GetRequiredService<IAuditingService>(),
                    provider.GetRequiredService<StandardRepository<TModel>()
                );
            }
        );
    } else {
        services.AddScoped(typeof(IRepository<TModel>), typeof(StandardRepository<TModel>));
    }

    return services;
});

рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреА рдХреБрдВрдЬреА рдУрдкрди рдЬреЗрдирд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИред рд╕реЗрд╡рд╛ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рд╣реЛрдиреЗ рдкрд░ рд╡реЗ рдмрдВрдж рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣ рдХреЗрд╡рд▓ рддрднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдмреВрдЯ рдкрд░ рд╕реЗрд╡рд╛ рдХреЛ рдХреИрд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рд╕реНрддрд░реАрдп рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕реЗрд╡рд╛ рдХреЛ рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдирд╛ рдЕрдЪреНрдЫрд╛ рд▓рдЧреЗрдЧрд╛ рдХрд┐ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдкрд░ рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рдХрд╛ рдХреНрдпрд╛ рд░реБрдЦ рд╣реИред рдЕрдЧрд░ рд╡реЗ рдХрднреА рднреА рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдареАрдХ рд╣реИ, рдореИрдВ рд╕рд┐рд░реНрдл рдЕрдиреНрдп рдбреАрдЖрдИ рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛ред рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдЕрдкрдиреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдЗрд╕рдХреЗ рдЦрд┐рд▓рд╛рдл рдЕрдкрдирд╛ рд╕рд┐рд░ рдкреАрдЯ рд▓рд┐рдпрд╛ рд╣реИред

рдЗрд╕рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ https://github.com/aspnet/DependencyInjection/issues/474 рдореЗрдВ рднреА рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдореБрдЭреЗ рдпрд╛рдж рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХреЛрдИ рдореБрджреНрджрд╛ рдерд╛, рдЪреИрдЯ рдореЗрдВ рдпрд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ, рд▓реЗрдХрд┐рди рдЗрд╕ рдкрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИред

рдзрдиреНрдпрд╡рд╛рдж, @рдЦреЗрд▓рдВрдЧред рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдХреНрдпрд╛ рд╣реИ, рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдореИрдк рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рдХреЗ рдбреАрдЖрдИ рдХреЗ рд╕рд╛рде рд░рдЪрдирд╛ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ ред рдЕрдЧрд▓реА рдмрд╛рд░ рдЬрдм рд╣рдореЗрдВ рдЕрдкрдиреЗ DI рд▓реЙрдЬрд┐рдХ рдореЗрдВ рдирд┐рд╡реЗрд╢ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рддреЛ рд╣рдордиреЗ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЙрд╕реА рддрд░рд╣ рдЬрд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИред

@рдЦреЗрд▓рдВрдЧ рдпрд╛рдж рд╣реИ рдХрд┐ рдЖрдк рдПрдХ рд╕рдордп рдореЗрдВ рдбреЗрдХреЛрд░реЗрдЯрд░ рд╕рдкреЛрд░реНрдЯ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рддреЗ рдереЗ?

рд╡реИрд╕реЗ рднреА, рд╕реЛрдЪрд╛ рдХрд┐ рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕реЗ рд▓рд╛рдЗрдЯрдЗрдВрдЬреЗрдХреНрдЯ рдореЗрдВ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

    using System;
    using System.Diagnostics;
    using System.Reflection;
    using LightInject;

    class Program
    {
        static void Main(string[] args)
        {            
            var container = new ServiceContainer();
            container.Register(typeof(IService<>), typeof(Service<>));
            container.Decorate(typeof(IService<>), typeof(ServiceDecorator<>),
                sr => sr.ImplementingType.GetGenericArguments()[0].GetTypeInfo().IsDefined(typeof(AuditedAttribute)));

            var fooService = container.GetInstance<IService<Foo>>();
            Debug.Assert(fooService is Service<Foo>);
            var barService = container.GetInstance<IService<Bar>>();
            Debug.Assert(barService is ServiceDecorator<Bar>);
        }
    }

    public interface IService<T>
    {
    }

    public class Service<T> : IService<T>
    {

    }

    public class ServiceDecorator<T> : IService<T>
    {
        public ServiceDecorator(IService<T> service)
        {
        }
    }


    public class AuditedAttribute : Attribute
    {
    }


    public class Foo
    {
    }

    [Audited]
    public class Bar
    {
    }

@seesharper рд╣рд╛рдБ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ NuGet рдкреИрдХреЗрдЬ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реБрдЖ рд╣реИ рдФрд░ рд╕реНрд░реЛрдд рдпрд╣рд╛рдБ рд╣реИ: https://github.com/khellang/Scrutor

рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдореБрджреНрджрд╛ рдмрдЪрд╛ рд╣реИ рдХрд┐ рд╡рд╣ рдУрдкрди рдЬреЗрдирд░рд┐рдХ рдХреЛ рд╕рдЬрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐, LightInject рдХреЗ рд╡рд┐рдкрд░реАрдд, MS.Ext.DI рдлрд╝реИрдХреНрдЯрд░реА рдЖрдкрдХреЛ ImplementingType рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рддрд░реНрдХреЛрдВ рдХреЛ рдЬрд╛рдирдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдкреВрдЫрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ...

@рдЦреЗрд▓рдВрдЧ рдиреЗ рдЗрд╕реЗ https://github.com/aspnet/DependencyInjection/issues/450 . рдкрд╛рдпрд╛

рд╣рдо рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдХреЛрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрднреА рднреА рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдпрд╛ рдкреНрд░рд╢реНрди рд╣реИрдВ, рддреЛ рдХреГрдкрдпрд╛ рдЕрдкрдиреЗ рдкрд╛рд╕ рдореМрдЬреВрдж рдХрд┐рд╕реА рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рд▓реЙрдЧ рдХрд░реЗрдВред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

sebastienros picture sebastienros  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jdom picture jdom  ┬╖  6рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

tarekgh picture tarekgh  ┬╖  11рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

uhaciogullari picture uhaciogullari  ┬╖  6рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

seesharper picture seesharper  ┬╖  9рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ