我使用带有Autofac的.Net 6,现在我有了一个控制器和两个服务:
public class TestController {
public ITestService TestService { get; set; }
public string Test() => TestService.Test();
}
public interface ITestService {
string Test();
}
public class TestService1 : ITestService {
public string Test() => "Test1";
}
public class TestService2 : ITestService {
public string Test() => "Test2";
}
我在Module
:中注册它们
public class AutofacModule : Autofac.Module {
// use assembly scanning to register: https://autofac.readthedocs.io/en/latest/register/scanning.html
protected override void Load(ContainerBuilder builder) {
builder.RegisterControllers().PropertiesAutowired().AsSelf();
builder.RegisterServices().AsImplementedInterfaces();
}
}
现在CCD_ 2将返回"0";测试1";因为注射了CCD_ 3。如果我想得到TestService2
(或其他实现的实例(,我需要使用构造函数来获取它
在Spring
中,@Resource("beanName")
可以指定要注入的实例,所以我想使用一个属性来匹配实例的名称,并像Spring:一样注入它
public class TestController {
[Resource("TestService2")]
public ITestService TestService { get; set; }
// return "Test2"
public string Test() => TestService.Test();
}
我该怎么办?
Autofac.Annotation成功了。
简而言之,它使用了AutowiredAttribute
(扩展ParameterFilterAttribute
(和流水线阶段,伪代码如下:
// Autofac.Module
protected override void Load(ContainerBuilder builder) {
// get all components that has `[Component]` attribute in process;
List<Type> components = GetComponents();
foreach (Type c in components) {
// register as self
var registration = builder.RegisterType(c).WithAttributeFiltering();
// get properties that has `[Autowired]` attribute
List<PropertyInfo> properties = GetProperties(c);
registration.ConfigurePipeline(pb =>
pb.Use(PipelinePhase.Activation, MiddlewareInsertionMode.StartOfPhase,
// the callback will be execute when components was resolved
(context, next) => {
next(context);
object instance = context.Instance;
foreach (PropertyInfo info in properties) {
// get component from container by `Autowired`'s options
context.TryResolveService(..., out object obj);
info.SetValue(intance, obj);
}
}
)
);
}
}