无需创建对象即可解析类型

时间:2012-02-28 18:01:20

标签: c# autofac

这是我的问题:我有一个容器,我将具体类型注册为接口。

builder.RegisterType<DeleteOrganization>().As<IDeleteOrganization>();

我正在为我正在进行的序列化项目实现SerializationBinder,而我需要实现的BindToType方法要求我返回一个Type对象。 BindToType方法为我提供了assemblyNametypeName(两个字符串)来帮助我创建一个类型对象。我想要做的是如果typeName是一个接口,我想问Autofac具体实现Type对于该接口Type是什么,而不实际创建该对象。这可能吗?

2 个答案:

答案 0 :(得分:10)

如果您使用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));
            }
        }
    }
}

答案 1 :(得分:2)

您可以很好地封装@Danielg的方法,以便可以让Autofac将类型列表注入构造器中。它要求您实现IRegistrationSource

就我而言,我想像这样从IConsoleCommand派生所有注册类型:

public Help(TypeList<IConsoleCommand> commands)
{
    _commands = commands;
}

我使用了一个简单的DTO-List来携带类型和要为其解析的T

public class TypeList<T> : List<Type>
{
    public TypeList(IEnumerable<Type> types) : base(types)
    {
    }
}

实际注册源的实现如下,其中<T>中的TypeList<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可以通过依赖项注入来解析类型。