Adr*_*eck 5 c# dependency-injection azure autofac azure-functions
是否可以使用面向方面的方法通过 Autofac 和 DynamicProxy 登录 Azure 函数,如下所示:
我研究了以下链接
然后尝试使用下面的代码扩展 Holger Leichsenring 的帖子(#1)。但是, Intercept() 函数从未被触发。有任何想法吗?
using Autofac.Extras.DynamicProxy;
using Castle.DynamicProxy;
Run Code Online (Sandbox Code Playgroud)
添加拦截器和一个带参数的函数...
[Intercept(typeof(ICallLogger))]
public class TestIt : ITestIt
{
public string Name { get; set; }
public string CallMe()
{
return "Dependency Injection Test method had been called...";
}
public string CallMeWithParameter(string parameter)
{
return "Dependency Injection Test method had been called with [" + parameter + "]";
}
}
Run Code Online (Sandbox Code Playgroud)
public class ServicesModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<CallLogger>().As<ICallLogger>();
builder.RegisterType<TestIt>().As<ITestIt>().EnableClassInterceptors();
// How can you pass context to the AutoFac.ServicesModule()? Commenting out for now and using parameterless constructor instead.
// builder.Register(c => new CallLogger(context.Trace)).Named<IInterceptor>("log-calls");
// Switch to use Type based interceptor attribute instead of Name based interceptor attribute
// builder.Register(c => new CallLogger()).Named<IInterceptor>("log-calls");
}
}
Run Code Online (Sandbox Code Playgroud)
public interface ICallLogger
{
void Intercept(IInvocation invocation);
}
/// <summary>
/// Logging class that would hopefully wrap TraceWriter - trying the Debug Output Window for now...
/// </summary>
public class CallLogger : IInterceptor, ICallLogger
{
TraceWriter _log;
public CallLogger(TraceWriter log)
{
_log = log;
}
public CallLogger()
{
_log = null;
}
public void Intercept(IInvocation invocation)
{
string message = string.Empty;
message = "Calling method {0} with parameters {1}... " +
invocation.Method.Name +
string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray());
if (_log != null)
{
_log.Info(message);
}
Debug.WriteLine(message);
invocation.Proceed();
message = "Done: result was {0}." + invocation.ReturnValue;
Debug.WriteLine(message);
if (_log != null)
{
_log.Info(message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用Autofac Type Interceptors可以做到这一点,但正如您所发现的,配置拦截器可能很棘手。我所知道的实现此目的的最简单方法是使用Functionless。完全公开,这是我编写的一个开源项目。我对自我推销不感兴趣,只是想帮助别人。我只在这里提到它,因为据我所知,这是实现您的目标的最简单方法,如果发布,我很乐意接受其他更好的解决方案。
这是一个完整的要点FunctionAppLogingInterception,您应该能够下载、构建和运行它,它演示了一个简单的日志记录拦截器。这是一个简短的解释...
host.json(请参阅Azure Functions 2.x 及更高版本的 host.json 参考) "logLevel": {
"FunctionAppLogingInterception": "Debug"
}
Run Code Online (Sandbox Code Playgroud)
IInterceptor自动拾取并注册。 public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
public可重写(即标记为virtual或)方法,如Autofac |所解释的那样。类型拦截器:提示。override public class ReportJob
{
[NewOrchestration]
public virtual async Task ExecuteAsync()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
POST /api/orchestrator?$method=ReportJob.<ExecuteAsync>()
Run Code Online (Sandbox Code Playgroud)
或者 ...
[FunctionName("reportjob-execute")]
public async Task Execute(
[HttpTrigger] HttpRequest request,
[DurableClient] IDurableOrchestrationClient client)
{
await client.DurablyInvokeAsync(
async () => await this.reportJob.ExecuteAsync()
);
}
Run Code Online (Sandbox Code Playgroud)
POST /api/reportjob-execute
Run Code Online (Sandbox Code Playgroud)
[2020-12-22T18:20:10.816Z] Host lock lease acquired by instance ID '000000000000000000000000D771FED2'.
[2020-12-22T18:20:16.207Z] Executing 'orchestrator' (Reason='This function was programmatically called via the host APIs.', Id=bdc7d19e-1250-4692-bde2-98cf663cacb8)
[2020-12-22T18:20:16.403Z] Executed 'orchestrator' (Succeeded, Id=bdc7d19e-1250-4692-bde2-98cf663cacb8, Duration=243ms)
[2020-12-22T18:20:16.481Z] Executing 'orchestration' (Reason='(null)', Id=2d17ea99-959c-43ef-b7ba-ed194de38165)
[2020-12-22T18:20:17.133Z] System.Threading.Tasks.Task ExecuteAsync() invoked
[2020-12-22T18:20:17.272Z] Executed 'orchestration' (Succeeded, Id=2d17ea99-959c-43ef-b7ba-ed194de38165, Duration=793ms)
[2020-12-22T18:20:17.339Z] Executing 'orchestration' (Reason='(null)', Id=ff5c08e7-f678-48a3-9a82-bc2e231195e3)
[2020-12-22T18:20:17.582Z] System.Threading.Tasks.Task GenerateReportsAsync() invoked
[2020-12-22T18:20:17.597Z] Executed 'orchestration' (Succeeded, Id=ff5c08e7-f678-48a3-9a82-bc2e231195e3, Duration=258ms)
[2020-12-22T18:20:17.642Z] Executing 'activity' (Reason='(null)', Id=cc4f89ef-f64c-4851-8e7c-3b7acbfcc915)
[2020-12-22T18:20:17.646Z] Executing 'activity' (Reason='(null)', Id=3a7747a6-5568-4561-a028-9c319263ccf7)
[2020-12-22T18:20:17.659Z] Executing 'activity' (Reason='(null)', Id=caea5602-9c0b-463a-b0b0-112e512eaf25)
[2020-12-22T18:20:17.808Z] System.Threading.Tasks.Task GenerateReportAsync() invoked
[2020-12-22T18:20:17.808Z] System.Threading.Tasks.Task GenerateReportAsync() invoked
[2020-12-22T18:20:17.808Z] System.Threading.Tasks.Task GenerateReportAsync() invoked
[2020-12-22T18:20:18.536Z] Executed 'activity' (Succeeded, Id=caea5602-9c0b-463a-b0b0-112e512eaf25, Duration=878ms)
[2020-12-22T18:20:18.540Z] Executed 'activity' (Succeeded, Id=cc4f89ef-f64c-4851-8e7c-3b7acbfcc915, Duration=901ms)
[2020-12-22T18:20:18.541Z] Executed 'activity' (Succeeded, Id=3a7747a6-5568-4561-a028-9c319263ccf7, Duration=897ms)
[2020-12-22T18:20:18.610Z] Executing 'orchestration' (Reason='(null)', Id=9500673c-7c4d-4d91-bfea-b6e095f51197)
[2020-12-22T18:20:18.716Z] System.Threading.Tasks.Task GenerateReportsAsync() invoked
[2020-12-22T18:20:18.728Z] Executed 'orchestration' (Succeeded, Id=9500673c-7c4d-4d91-bfea-b6e095f51197, Duration=120ms)
[2020-12-22T18:20:18.782Z] Executing 'orchestration' (Reason='(null)', Id=8c9dc2d6-71f9-47b0-8c1a-4409da6b23d7)
[2020-12-22T18:20:18.896Z] System.Threading.Tasks.Task ExecuteAsync() invoked
[2020-12-22T18:20:18.901Z] Executed 'orchestration' (Succeeded, Id=8c9dc2d6-71f9-47b0-8c1a-4409da6b23d7, Duration=120ms)
Run Code Online (Sandbox Code Playgroud)
有关 Functionless 如何实现这一点的更多信息,请参阅其Autofac 模块实现,其中包含以下代码片段,如果您想使用 Autofac 但不使用 Functionless 获得类似的结果,该代码片段可以适用于许多其他场景......
assemblies.ForEach(
assembly => builder
.RegisterAssemblyTypes(assembly)
.Where(p => p.IsPublic && p.IsClass)
.AsSelf().AsImplementedInterfaces()
.PreserveExistingDefaults()
.EnableClassInterceptors()
.InterceptedBy(interceptorTypes)
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
495 次 |
| 最近记录: |