如何在asp.net-core webapi中使用unity-container拦截

时间:2018-06-05 11:41:47

标签: c# asp.net-core unity-container asp.net-core-2.0 asp.net-core-webapi

如果我尝试在asp.net-core webapi中使用统一拦截,我的呼叫处理程序永远不会被调用。我知道它适用于.net-core控制台应用程序,非核心应用程序,甚至是同一个项目中没有webapi的测试(从测试容器中解析服务)。

以下是我用来设置api的(相关)代码:

Program.cs

.UseUnityServiceProvider()

Startup.cs

public void ConfigureContainer(IUnityContainer container) {
    container.AddNewExtension<Interception>();
    container.RegisterType<IProjectService, ProjectService>().Configure<Interception>().SetInterceptorFor<IProjectService>(new InterfaceInterceptor());
}

public void ConfigureServices(IServiceCollection services) {
    ...
    services.AddControllersAsServices();
    ...
}

我怀疑它与Unity.Microsoft.DependencyInjection.ServiceProvider设置的UseUnityServiceProvider()有关,因为拦截方式没有解决这些类型。

那么我需要做些什么才能让拦截工作正常进行?或者这是某个已知的错误?

[更新]

@Albert:你的意思是这样的:

container.RegisterType<IProjectService, ProjectService>(new InterceptionBehavior<PolicyInjectionBehavior>()); // new Interceptor<InterfaceInterceptor>()

即使我将InterfaceInterceptor添加为第二个参数,它也不会改变任何内容。

我用于测试目的的HandlerAttribute和CallHandler的更多信息:

public class DummyLoggingAttribute : HandlerAttribute {
    public override ICallHandler CreateHandler(IUnityContainer container) 
        return new DummyLoggerCallHandler(){Order = 2};
    }
}

public class DummyLoggerCallHandler : ICallHandler{
    private int _order;

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
        Console.WriteLine("log vor ");

        IMethodReturn result = getNext()(input, getNext);

        Console.WriteLine("log danach ");
        return result;
    }

    public int Order {
        get { return _order; }
        set { _order = value; }
    }
}

应用于以下方法。

[DummyLogging]
public virtual IList<Project> GetAllProjects() {
    return _projectDao.GetAll();
}

如果我将属性添加到接口,实现或两者,它甚至没有任何区别。

我是另一个.net-core控制台应用程序我甚至可以成功使用以下扩展来自动配置每个注册类型以进行拦截。

/// <summary>
///     Extension für das automatische Intercepten von Methoden
/// </summary>
public class InterceptionExtension : UnityContainerExtension {
    /// <summary>
    ///     Entfernt die Extension
    /// </summary>
    public override void Remove() {
        Context.Registering -= OnRegister;
        Context.RegisteringInstance -= OnRegisterInstance;
    }

    /// <summary>
    ///     Initialisiert die Extension
    /// </summary>
    protected override void Initialize() {
        Container.AddNewExtension<Interception>();

        Context.Registering += OnRegister;
        Context.RegisteringInstance += OnRegisterInstance;
    }

    /// <summary>
    ///     Event wenn ein Type Registriert wird
    /// </summary>
    private void OnRegister(object sender, RegisterEventArgs e) {
        if (e.TypeFrom != null) {
            Container.Configure<Interception>()
                    .SetInterceptorFor(e.TypeFrom, new InterfaceInterceptor());
        }
    }

    /// <summary>
    ///     Event wenn eine Instance Regestriert wird
    /// </summary>
    private void OnRegisterInstance(object sender, RegisterInstanceEventArgs e) {
        Container.Configure<Interception>()
                .SetInterceptorFor(e.RegisteredType, new InterfaceInterceptor());
    }
}

这使我认为注册拦截不是问题,而是通过UnityServiceProvider解决服务问题。

1 个答案:

答案 0 :(得分:0)

我不确定这是问题的答案。 据我所知,最初的问题是必须拦截ProjectService的方法调用的代理类没有被创建。 我能够通过创建一个派生自IInterceptionBehavior的类和一些不同的类型注册来修复它。

<强> MyInterceptionBehavior:

public class MyInterceptionBehavior : IInterceptionBehavior
{
    public bool WillExecute
    {
        get { return true; }
    }

    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Enumerable.Empty<Type>();
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        IMethodReturn result = getNext()(input, getNext);
        Console.WriteLine("Interception Called");
        return result;
    }

}

并在ConfigureContainer()中将此IProjectService注册替换为:

container.RegisterType<IProjectService, ProjectService>(
    new Interceptor<InterfaceInterceptor>(),
    new InterceptionBehavior<MyInterceptionBehavior>());
每次调用Invoke的每个方法时都会调用

IProjectService方法。我希望这会给你一些想法或帮助你做出截取行为的工作。