开发者

Autofac wiring question - beginner

开发者 https://www.devze.com 2023-02-14 19:04 出处:网络
Beginners question: Given two classes: Myclass5 and Myclass6 how can one wire up following factory method (returned as Func)

Beginners question: Given two classes: Myclass5 and Myclass6 how can one wire up following factory method (returned as Func) such that myclass5 and myclass6 instances and IMyClass that they depend on are all retrieved via autofac (assuming that these three instances are registered).

   public static MyClass4 FactoryMethod(int nu)
    {
        if (nu == 1)
            return new MyClass5(....);
开发者_如何学C        if (nu == 4)
            return new MyClass6(....);

        throw new NotImplementedException();
    }

public abstract class MyClass4
{

}

public class MyClass5 : MyClass4
{
    public MyClass5(int nu, IMyClass a)
    {

    }
}

public class MyClass6 : MyClass4
{
    public MyClass6(int nu, IMyClass a)
    {

    }
}


For FactoryMethod to be able to create the instances, it requires access to a container. I would suggest create a delegate type for the factory method, which makes it easy to take dependency on it. Registration goes like this:

var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.Register((c, p) =>
    {
        var context = c.Resolve<IComponentContext>();
        return new FactoryMethod(nu =>
            {
                var nuParameter = TypedParameter.From(nu);
                switch (nu)
                {
                    case 1:
                        return context.Resolve<MyClass5>(nuParameter);
                    case 4:
                        return context.Resolve<MyClass6>(nuParameter);
                    default:
                        throw new NotImplementedException();
                }
            });
        });

var container = cb.Build();

At resolve time, you can then take a dependency on the FactoryMethod delegate type and use it to resolve instances:

var factory = container.Resolve<FactoryMethod>();
var instance5 = factory(1);
var instance6 = factory(1);

Note: the delegate instance we're creating needs a context. We cannot use the c parameter directly since that context is only temporary. Thus we must resolve a IComponentContext to "bake" into the lambda.

Update: if you would like to extract the factory implementation into a method that is not dependent on the container I would suggest the following:

    public class FactoryMethodImpl
    {
        readonly Func<int, MyClass5> _factory5;
        readonly Func<int, MyClass6> _factory6;

        public FactoryMethodImpl(Func<int, MyClass5> factory5, Func<int, MyClass6> factory6)
        {
            _factory5 = factory5;
            _factory6 = factory6;
        }

        public MyClass4 Create(int nu)
        {
            switch (nu)
            {
                case 1:
                    return _factory5(nu);
                case 4:
                    return _factory6(nu);
                default:
                    throw new NotImplementedException();
            }
        }
    }

Now, change the registration code to this:

var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.RegisterType<FactoryMethodImpl>().SingleInstance();
cb.Register(c=> new FactoryMethod(c.Resolve<FactoryMethodImpl>().Create));
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号