рдпрд╣ рдПрдХ рд╕реБрд╡рд┐рдзрд╛ рдЕрдиреБрд░реЛрдз рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ рдпрджрд┐ рдпрд╣ рдЧрд▓рдд рдкреНрд░рд╛рд░реВрдк/рдЧрд▓рдд рд╕реНрдерд╛рди рд╣реИред
рдПрд╕реНрдкрдиреЗрдЯ/рд▓реЙрдЧрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдореИрдВ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ рдЬрд┐рд╕рдореЗрдВ рдореИрдВ рдЧреИрд░-рдЬреЗрдиреЗрд░рд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ 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 рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ "рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ" рд▓рд╛рдПрдЧрд╛ред рдЕрдЪрд╛рдирдХ, рдЙрди рд╕рднреА рдХреЛ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ред
рд╢рд╛рдпрдж рдЗрд╕реЗ рдЖрдЧреЗ рдХреА рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
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 . рдкрд╛рдпрд╛
рд╣рдо рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдХреЛрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрднреА рднреА рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдпрд╛ рдкреНрд░рд╢реНрди рд╣реИрдВ, рддреЛ рдХреГрдкрдпрд╛ рдЕрдкрдиреЗ рдкрд╛рд╕ рдореМрдЬреВрдж рдХрд┐рд╕реА рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рд▓реЙрдЧ рдХрд░реЗрдВред
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдЦреБрд▓реЗ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╕рдЬрд╛рд╡рдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдПрдХ рд╕рдорд╛рди, рд▓реЗрдХрд┐рди рдереЛрдбрд╝реА рдЕрд▓рдЧ рд╕реБрд╡рд┐рдзрд╛ рдорд╛рдВрдЧреА рд╣реИ; рдлрд╝реИрдХреНрдЯрд░реА рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдореЗрдВ рдЕрдиреБрд░реЛрдзрд┐рдд рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред
рдЙрджрд╛рд╣рд░рдг:
рдЬрд╣рд╛рдВ
context.RequestedType
рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реЗрд╡рд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЕрд░реНрдерд╛рддprovider.GetService<IService<string>>()
->typeof(IService<string>)
редрдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдореБрдЦреНрдп рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ MS.Ext.DI рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ "рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ" рд▓рд╛рдПрдЧрд╛ред рдЕрдЪрд╛рдирдХ, рдЙрди рд╕рднреА рдХреЛ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ред