-
How to use with DI? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
This is not a final solution for DI problem, we still work on it, but 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...");
}
} |
Beta Was this translation helpful? Give feedback.
-
@pamidur public class TestClass
{
// Token: 0x0600000D RID: 13 RVA: 0x0000223A File Offset: 0x0000043A
public TestClass(LogAspect logAspect)
{
this.xxxxLogAspect= logAspect. //change the constractor.
}
// Token: 0x0600000C RID: 12 RVA: 0x00002227 File Offset: 0x00000427
[Log]
public void Do()
{
this.xxxLogAspect.LogEnter("Do");
}
protected LogAspect xxxLogAspect;
} |
Beta Was this translation helpful? Give feedback.
This is not a final solution for DI problem, we still work on it, but
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.
You can still use
Scope.PerInstance
but then make sure you manage your instance TelemetryClient properly (e.g. create one in static constructor of…