-
Notifications
You must be signed in to change notification settings - Fork 116
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
How to Inject TelemetryClient (with autoflush) or pass any other runtime object to the aspect (.net core 3.1 console app) #128
Comments
Hi @pamswam, Ok let's see what options we have: Option 1: Create and manage logger inside aspect: This is quite easy provided you use global aspects. Global aspects are singletons by themselves. So everything you create in their constructor are singletons as well. [Aspect(Scope.Global)]
public class LogAspect : Attribute
{
private readonly TelemetryClient_logger;
public LogAspect(ILogger logger)
{
_logger = new TelemetryClient();
}
... You can still use Option 2: Manage runtime objects with IoC container and inject all you need trough constructor: You need a static class with a static method: public static object GetInstance(Type type) Then tell your aspect to use this class as a factory (use can use Global scope as well): [Aspect(Scope.PerInstance, Factory = typeof(ApplicationServices))]
public class LogAspect Then request TelemetryClient from constructor private readonly TelemetryClient _logger;
public LogAspect(TelemetryClient logger)
{
_logger = logger;
} Then you can use any IoC container to setup your services, in example below I use Microsoft.Extensions.DependencyInjection. It requires all services to be registered, so I had to register both .AddTransient<LogAspect>()
.AddSingleton<TelemetryClient>() One thing to pay attention to is since Aspect has constructor injection, you can't have it as Attribute. so you need a separate Attribute like this: [Injection(typeof(LogAspect))]
public class LogAttribute : Attribute
{
} Full code below (you can copy/paste to experiment yourself): public static class ApplicationServices
{
public static readonly ServiceProvider ServiceProvider;
static ApplicationServices()
{
ServiceProvider = new ServiceCollection()
.AddTransient<LogAspect>()
.AddSingleton<TelemetryClient>()
.BuildServiceProvider();
}
public static object GetInstance(Type type) => ServiceProvider.GetRequiredService(type);
}
class Program
{
static void Main(string[] args)
{
new TestClass().Do();
}
}
[Log]
public class TestClass
{
public void Do() { }
}
[Injection(typeof(LogAspect))]
public class LogAttribute : Attribute
{
}
[Aspect(Scope.PerInstance, Factory = typeof(ApplicationServices))]
public class LogAspect
{
private readonly TelemetryClient _logger;
public LogAspect(TelemetryClient logger)
{
_logger = logger;
}
[Advice(Kind.Before)]
public void LogEnter([Argument(Source.Name)] string name)
{
_logger.TrackEvent($"Calling '{name}' method...");
}
} |
Awesome! Will give a try! |
Thanks for using it, it encourages me to develop it further. Feel free to share your questions, feedback and feature requests! |
I started with UniversalWrapper sample with logger injected as above. |
@GioviQ , statics aren't mandatory at all, feel free to make them instance methods. |
There are a few mandatory things in AspectInjector e.g. 'Around advice should return object', but these limitations are enforced by both compiler and roslyn analyzer. So as a rule - if it compiles successfully - it is valid code for aspect injector :) |
Thank you @pamidur it's working now. See https://github.com/enkodellc/blazorboilerplate/blob/development/src/Server/BlazorBoilerplate.Server/Aop/ApiResponseExceptionAspect.cs Maybe it can be written with less code. |
@GioviQ Looks good to me. Currenty I am afraid this is least possible amount of code, although we have plans for generic Around advices for future releases. |
Hi there,
Please can you show some light on how to pass runtime objects (or create and manage logger inside the aspect, ideally a singleton)
Writing to Console.Writeline works, however in production, writing to console is not sufficient.
Many thanks!
The text was updated successfully, but these errors were encountered: