C# 无法使用ASP.NET Core 2和Castle.Core的手动拦截来解析一般服务
我知道有很多类似的问题,但实际上没有一个解决了我的问题。 我创建了一个新的Asp.NETCore2应用程序。 现在,我尝试使用特定服务的拦截器将一些数据获取到此服务中(我使用的是C# 无法使用ASP.NET Core 2和Castle.Core的手动拦截来解析一般服务,c#,dependency-injection,autofac,asp.net-core-2.0,castle,C#,Dependency Injection,Autofac,Asp.net Core 2.0,Castle,我知道有很多类似的问题,但实际上没有一个解决了我的问题。 我创建了一个新的Asp.NETCore2应用程序。 现在,我尝试使用特定服务的拦截器将一些数据获取到此服务中(我使用的是Castle.Corenuget包)。 我有一个通用的IConfigurationInterceptor和一个真正的实现ConfigurationInterceptor 以下是界面: public interface IConfigurationInterceptor<T> : IInterceptor wh
Castle.Core
nuget包)。
我有一个通用的IConfigurationInterceptor
和一个真正的实现ConfigurationInterceptor
以下是界面:
public interface IConfigurationInterceptor<T> : IInterceptor where T : class { }
public class ConfigurationInterceptor<T> : IConfigurationInterceptor<T> where T : class
{
public ConfigurationInterceptor(ConfigurationInfo<T> configurationInfo,
some other services)
{
_configurationInfo = configurationInfo;
//.....
}
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue = somefunc(someconfig, invocation.Arguments);
}
}
在我的ConfigureServices
中,我有以下两行:
services.AddSingleton(typeof(IConfigurationInterceptor<>),
typeof(ConfigurationInterceptor<>));
services.AddSingletonConfiguration<IStaticDataConfiguration, StaticDataConfiguration>(
"SomeFeatureKey");
扩展方法是这样的:
public static void RegisterConfiguration<TInterface, TImplementation>(
this ContainerBuilder builder, string featureName)
where TImplementation : class, TInterface
{
var info = new ConfigurationInfo<TImplementation>(featureName, typeof(TInterface));
var generator = new ProxyGenerator();
builder
.Register(c =>
{
var ic = c.Resolve<Func<ConfigurationInfo<TImplementation>,
IConfigurationInterceptor<TImplementation>>>()(info);
return generator.CreateInterfaceProxyWithoutTarget(info.ServiceType, ic);
})
.As<TInterface>()
.SingleInstance();
}
公共静态无效注册表配置(
此ContainerBuilder生成器,字符串特征名称)
其中TImplementation:类,TInterface
{
var info=新配置信息(功能名称、类型(TInterface));
var生成器=新的ProxyGenerator();
建设者
.寄存器(c=>
{
var ic=c.Resolve()(信息);
返回生成器.CreateInterfaceProxyWithoutTarget(info.ServiceType,ic);
})
.As()
.SingleInstance();
}
任何帮助都会得到报答
编辑1:
现在,我从方法GetService
更改为方法GetRequiredService
,并引发如下异常:
public static void AddSingletonConfiguration<TInterface, TImplementation>(
this IServiceCollection services, string featureName)
where TImplementation : class, TInterface where TInterface : class
{
var info = new ConfigurationInfo<TImplementation>(featureName, typeof(TInterface));
var generator = new ProxyGenerator();
services.AddSingleton(x =>
{
var ic = x.GetService<Func<ConfigurationInfo<TImplementation>,
IConfigurationInterceptor<TImplementation>>>();
var icTemp = ic.Invoke(info);
return (TInterface) generator.CreateInterfaceProxyWithoutTarget(
info.ServiceType, icTemp);
});
}
public void ConfigureServices(IServiceCollection services)
{
IConfigurationInterceptor<T> GetConfigurationInterceptor<T>(ConfigurationInfo<T> info) where T : class
{
return new ConfigurationInterceptor<T>(info, services.GetService<IConfigurationProvider>(), Configuration);
}
services.AddSingletonConfiguration<IStaticDataConfiguration, StaticDataConfiguration>("someFeatureKey", GetConfigurationInterceptor);
}
public static void AddSingletonConfiguration<TInterface, TImplementation>(this IServiceCollection services,
string featureName, Func<ConfigurationInfo<TImplementation>, IConfigurationInterceptor<TImplementation>> ic) where TImplementation : class, TInterface where TInterface : class
{
var info = new ConfigurationInfo<TImplementation>(featureName, typeof(TInterface));
var generator = new ProxyGenerator();
services.AddSingleton(x =>
{
var icTemp = ic.Invoke(info);
return (TInterface) generator.CreateInterfaceProxyWithoutTarget(info.ServiceType, icTemp);
});
}
public static TInterface GetService<TInterface>(this IServiceCollection services) where TInterface : class
{
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<TInterface>();
}
“System.Func'2[StaticDataProvider.DomainModel.ConfigurationInfo'1[StaticDataProvider.Services.StaticDataConfiguration],StaticDataProvider.Services.Interfaces.IConfigurationInterceptor'1[StaticDataProvider.Services.StaticDataConfiguration]]”类型的服务尚未注册
编辑2:
总而言之,问题是:在我当前的Asp.Net core项目中,我无法获得Func
,而在Asp.Net MVC 5项目中(这是一个完全不同的项目),我可以使用Autofac获得Func
。我认为这与Autofac默认提供的参数化实例化功能有关:
现在,我不知道Asp.Net核心默认DI容器中是否有类似这种“参数化实例化”功能,它允许我解析
Func
,而不是B
,,我猜问题的根源在于拦截器相当复杂的手动布线
如果您将拦截器与Autofac一起使用,最好使用Autofac.Extras.dynamicProxy 2
包,而不是尝试将一系列分辨率与函数和参数链接在一起。我在这里看到了很多小问题,比如如何在没有目标的情况下设置单例接口代理,但我不完全清楚如何在事后添加目标。使用提供的工具可以避免很多复杂性
也就是说,我也在查看异常消息。如果没有堆栈跟踪,我无法100%保证,但在Autofac源上搜索表明,这不是来自Autofac的消息-很可能是来自默认Microsoft.Extensions.DependencyInjection容器的消息。这表明你可能并没有像你想象的那样把每件事都联系起来
我会备份一点,让简单的东西正常工作,并确保它们来自Autofac。如果您决定不使用Autofac,请确保已将其从等式中完全删除。基本上,只要确保它是干净的,并在一般意义上工作
之后,慢慢地把东西加回去,一次一个。我可能会建议在单元测试中进行复制,在单元测试中,您可以使用这些注册机制,并在不降低整个应用程序复杂性的情况下工作。从那里解开它。如果它太复杂而无法进行单元测试。。。也许这是一个指标,你应该简化它并重构它。使其可测试。我猜问题的根源在于拦截器相当复杂的手动接线 如果您将拦截器与Autofac一起使用,最好使用
Autofac.Extras.dynamicProxy 2
包,而不是尝试将一系列分辨率与函数和参数链接在一起。我在这里看到了很多小问题,比如如何在没有目标的情况下设置单例接口代理,但我不完全清楚如何在事后添加目标。使用提供的工具可以避免很多复杂性
也就是说,我也在查看异常消息。如果没有堆栈跟踪,我无法100%保证,但在Autofac源上搜索表明,这不是来自Autofac的消息-很可能是来自默认Microsoft.Extensions.DependencyInjection容器的消息。这表明你可能并没有像你想象的那样把每件事都联系起来
我会备份一点,让简单的东西正常工作,并确保它们来自Autofac。如果您决定不使用Autofac,请确保已将其从等式中完全删除。基本上,只要确保它是干净的,并在一般意义上工作
之后,慢慢地把东西加回去,一次一个。我可能会建议在单元测试中进行复制,在单元测试中,您可以使用这些注册机制,并在不降低整个应用程序复杂性的情况下工作。从那里解开它。如果它太复杂而无法进行单元测试。。。也许这是一个指标,你应该简化它并重构它。让它可测试。我将把我以前的答案留给后代,但是。。。默认的Microsoft IoC提供程序非常简单,不支持Autofac的所有功能。您将无法从中获得参数化分辨率或自动生成工厂。我将把以前的答案留给后代,但是。。。默认的Microsoft IoC提供程序非常简单,不支持Autofac的所有功能。您无法从中获得参数化分辨率或自动生成工厂。以下是我必须做的: 修改的
ConfigureService
方法如下:
public static void AddSingletonConfiguration<TInterface, TImplementation>(
this IServiceCollection services, string featureName)
where TImplementation : class, TInterface where TInterface : class
{
var info = new ConfigurationInfo<TImplementation>(featureName, typeof(TInterface));
var generator = new ProxyGenerator();
services.AddSingleton(x =>
{
var ic = x.GetService<Func<ConfigurationInfo<TImplementation>,
IConfigurationInterceptor<TImplementation>>>();
var icTemp = ic.Invoke(info);
return (TInterface) generator.CreateInterfaceProxyWithoutTarget(
info.ServiceType, icTemp);
});
}
public void ConfigureServices(IServiceCollection services)
{
IConfigurationInterceptor<T> GetConfigurationInterceptor<T>(ConfigurationInfo<T> info) where T : class
{
return new ConfigurationInterceptor<T>(info, services.GetService<IConfigurationProvider>(), Configuration);
}
services.AddSingletonConfiguration<IStaticDataConfiguration, StaticDataConfiguration>("someFeatureKey", GetConfigurationInterceptor);
}
public static void AddSingletonConfiguration<TInterface, TImplementation>(this IServiceCollection services,
string featureName, Func<ConfigurationInfo<TImplementation>, IConfigurationInterceptor<TImplementation>> ic) where TImplementation : class, TInterface where TInterface : class
{
var info = new ConfigurationInfo<TImplementation>(featureName, typeof(TInterface));
var generator = new ProxyGenerator();
services.AddSingleton(x =>
{
var icTemp = ic.Invoke(info);
return (TInterface) generator.CreateInterfaceProxyWithoutTarget(info.ServiceType, icTemp);
});
}
public static TInterface GetService<TInterface>(this IServiceCollection services) where TInterface : class
{
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<TInterface>();
}
public void配置服务(IServiceCo)