Constructor Injection - Do we inject factories as well?

前端 未结 3 1134
一整个雨季
一整个雨季 2021-02-15 07:08

After listening to the Clean Code Talks, I came to understand that we should use factories to compose objects. So, for example, if a House has a Door a

相关标签:
3条回答
  • 2021-02-15 07:34

    If you end up using Unity, I have recently implemented an equivalent of Castle Windsor Typed Factories for Unity. You can find the project at https://github.com/PombeirP/Unity.TypedFactories, and the NuGet package at http://nuget.org/packages/Unity.TypedFactories.

    The usage is the following:

    unityContainer
        .RegisterTypedFactory<IFooFactory>()
        .ForConcreteType<Foo>();
    

    You just have to create the IFooFactory interface with a method returning IFoo, and the rest is done for you by the library. You can resolve IFooFactory and use it to create IFoo objects straight away.

    0 讨论(0)
  • 2021-02-15 07:39

    If you inject too many factories that is a code smell called constructor over-injection that indicates your class is doing too much.

    Many containers provide a feature called auto-factories. That means they generate factories of type Func<T>automatically if they know how to generate T.

    Castle Windsor has an advanced feature called Typed Factory facilities which generates implementations of a factory interface on-the-fly.

    There is also a port of typed factories for Unity in the TecX project.

    0 讨论(0)
  • 2021-02-15 07:44

    Staying with the Door and DoorKnob example, you don't inject a factory - you inject the DooKnob itself:

    public class Door
    {
        private readonly DoorKnob doorKnob;
    
        public Door(DoorKnob doorKnob)
        {
            if (doorKnob == null)
                throw new ArgumentNullException("doorKnob");
    
            this.doorKnob = doorKnob;
        }
    }
    

    No factories are in sight in this level.

    House, on the other hand, depends on Door, but not on DoorKnob:

    public class House
    {
        private readonly Door door;
    
        public House(Door door)
        {
            if (door == null)
                throw new ArgumentNullException("door");
    
            this.door = door;
        }
    }
    

    This keeps options open until at last you have to compose everything in the application's Composition Root:

    var house = new House(new Door(new DoorKnob()));
    

    You can use a DI Container to compose at this level, but you don't have to. No factories are involved.

    0 讨论(0)
提交回复
热议问题