工厂和国际奥委会在一起 - 如何使用呢?

时间:2016-06-21 20:43:06

标签: c# .net inversion-of-control autofac factory-pattern

所以我有这个应用程序,我使用IOC(autofac)。与此同时,我发现自己处于需要工厂的位置。在工厂内部,我创建了具有依赖关系的新对象 - 所以现在我想知道,我怎么能嫁给这些?

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory
{
    public ISubscriptionHandler GetProvider(StreamType streamType)
    {
        switch (streamType)
        {
            case StreamType.Rss:
                return new RssSubscriptionHandler(null,null,null,null);
            case StreamType.Person:
                return new PersonSubscriptionHandler(null, null, null, null);
            default:
                throw new ArgumentOutOfRangeException(nameof(streamType), streamType, null);
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您可以使用named and keyed service并使用IIndex<TKey, TService>

检索实例

注册可能如下所示:

builder.RegisterType<RssHandler>().Keyed<ISubscriptionHandler>(StreamType.Rss);
builder.RegisterType<PersonHandler>().Keyed<ISubscriptionHandler>(StreamType.Person);
builder.RegisterType<SubscriptionHandlerFactory>().As<ISubscriptionHandlerFactory>();

和像这样的工厂:

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory
{
    public SubscriptionHandlerFactory(IIndex<StreamType, ISubscriptionHandler> handlers)
    {
        this._handlers = handlers;
    }

    private readonly IIndex<StreamType, ISubscriptionHandler> _handlers;

    public ISubscriptionHandler GetProvider(StreamType streamType)
    {
        return this._handlers[streamType];
    }
}

答案 1 :(得分:0)

您无法使用IoC永远抽象出对象的实例化。在某些时候,您将不得不创建一个具体的实例(在工厂内或您的IoC容器中)

您可以将autofac容器注入工厂,或者由于工厂本身实现了接口,因此您可以将工厂的不同版本注入到类可能需要的工厂中(例如,如果您需要不同的工厂进行单元测试) )

答案 2 :(得分:0)

我解决了。的种类。因为我不想依赖Autofac它自己被撕裂了。但是感谢@ martin-costello我觉得我可能不需要使用autofac,但是IDependencyResolver的构建不那么邪恶。由于我无法将autofac注册为IDependencyResolver,因此我将DependencyResolver注册为IDependencyResolver。再迈近一步。由于注册发生在autofac DependencyResolver.SetResolver发生之前,我需要使用Lazy,这最终解决了我的问题。

此处的代码(或至少是我发现的最佳解决方案)

// other registration
builder.RegisterType<RssSubscriptionHandler>();
builder.RegisterType<PersonSubscriptionHandler>();
// even more registration here

builder.RegisterType<SubscriptionHandlerFactory>()
       .As<ISubscriptionHandlerFactory>()
       .WithParameter(new TypedParameter(typeof(Lazy<IDependencyResolver>), 
                      new Lazy<IDependencyResolver>(() => DependencyResolver.Current)));

然后工厂更改为此(清理前):

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory
{
    private readonly Lazy<IDependencyResolver> resolver;

    public SubscriptionHandlerFactory(Lazy<IDependencyResolver> resolver)
    {
        this.resolver = resolver;
    }

    public ISubscriptionHandler GetProvider(StreamType streamType)
    {
        switch (streamType)
        {
            case StreamType.Rss:
                return (ISubscriptionHandler)this.resolver.Value.GetService(typeof(RssSubscriptionHandler));
            case StreamType.Person:
                return (ISubscriptionHandler)this.resolver.Value.GetService(typeof(PersonSubscriptionHandler));
            default:
                throw new ArgumentOutOfRangeException(nameof(streamType), streamType, null);
        }
    }
}

现在这是最好/干净/不那么邪恶/不那么具体/抽象/无论我能解决什么解决方案。欢迎任何评论。