在不创建对象的情况下解析类型
本文关键字:类型 情况下 创建对象 | 更新日期: 2023-09-27 18:26:14
我的问题是:我有一个容器,在其中我将具体类型注册为接口。
builder.RegisterType<DeleteOrganization>().As<IDeleteOrganization>();
我正在为正在执行的序列化项目实现SerializationBinder
,并且需要实现的BindToType
方法希望我返回一个Type
对象。BindToType
方法给了我一个assemblyName
和typeName
(都是字符串)来帮助我创建一个类型对象。我想做的是,如果typeName
是一个接口,我想问Autofac Type
对接口Type
的具体实现是什么,而不需要它实际创建对象。这可能吗?
如果您使用RegisterType注册服务,这是可能的。我写了一个快速测试,可以帮助您提取所需的数据。
private interface IDeleteOrganization
{
}
private class DeleteOrganization : IDeleteOrganization
{
}
[TestMethod]
public void CanResolveConcreteType()
{
var builder = new ContainerBuilder();
builder.RegisterType()
.As();
using(var container = builder.Build())
{
var registration = container.ComponentRegistry
.RegistrationsFor(new TypedService(typeof (IDeleteOrganization)))
.SingleOrDefault();
if (registration != null)
{
var activator = registration.Activator as ReflectionActivator;
if (activator != null)
{
//we can get the type
var type = activator.LimitType;
Assert.AreEqual(type, typeof (DeleteOrganization));
}
}
}
}
您可以很好地封装@Danielg的方法,这样您就可以让Autofac将类型列表注入到构造器中。它要求您实现IRegistrationSource
。
在我的案例中,我想获得从IConsoleCommand
派生的所有注册类型,比如:
public Help(TypeList<IConsoleCommand> commands)
{
_commands = commands;
}
我使用了一个简单的DTO列表来携带类型和我想解析它们的T
:
public class TypeList<T> : List<Type>
{
public TypeList(IEnumerable<Type> types) : base(types)
{
}
}
实际的注册源实现如下,其中TypeList<T>
中的<T>
用于匹配已注册并且我们想要检索的接口类型。
internal class TypeListSource<T> : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
if (service is IServiceWithType swt && typeof(TypeList<T>).IsAssignableFrom(swt.ServiceType))
{
var registration =
new ComponentRegistration(
id: Guid.NewGuid(),
activator: new DelegateActivator(swt.ServiceType, (context, p) =>
{
var types =
context
.ComponentRegistry
.RegistrationsFor(new TypedService(typeof(T)))
.Select(r => r.Activator)
.OfType<ReflectionActivator>()
.Select(activator => activator.LimitType);
return new TypeList<T>(types);
}),
services: new[] {service},
lifetime: new CurrentScopeLifetime(),
sharing: InstanceSharing.None,
ownership: InstanceOwnership.OwnedByLifetimeScope,
metadata: new Dictionary<string, object>()
);
return new IComponentRegistration[] {registration};
}
// It's not a request for the base handler type, so skip it.
else
{
return Enumerable.Empty<IComponentRegistration>();
}
}
public bool IsAdapterForIndividualComponents => false;
}
最后,您必须使用将其添加到builder
builder.RegisterSource(new TypeListSource<IConsoleCommand>());
现在,Autofac可以通过依赖注入来解析类型。