5

Why does .net MVC source code ControllerBuilder use a delegate to assign the controller factory?:

private Func<IControllerFactory> _factoryThunk;

public void SetControllerFactory(IControllerFactory controllerFactory) {
    _factoryThunk = () => controllerFactory;
}

Why can't it just assign the ControllerFactory directly?, ie:

private IControllerFactory _factory;

public void SetControllerFactory(IControllerFactory controllerFactory) {
    _factory = controllerFactory;
}

public void SetControllerFactory(Type controllerFactoryType) {
    _factory = (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
}

1 Answer 1

4

The reason that _factoryThunk is currently defined as a Func<IControllerFactory> is that it's a generic means to support both overloads:

void SetControllerFactory(Type);
void SetControllerFactory(IControllerFactory);

The implementation of the first one uses the fact that _factoryThunk is a Func by declaring that Func inline by using Activator to instantiate the Type lazily:

this._factoryThunk = delegate {
    IControllerFactory factory;
    try
    {
        factory = (IControllerFactory) Activator.CreateInstance(controllerFactoryType);
    }
    catch (Exception exception)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, new object[] { controllerFactoryType }), exception);
    }
    return factory;
};

Therefore, the reason the other overload looks like it has a spurious implementation is that since _factoryThunk is declared as a Func, the line you propose wouldn't have even compiled:

_factoryThunk = controllerFactory;

_factoryThunk is a Func<IControllerFactory> whereas controllerFactory is an IControllerFactory -- incompatible types.

Sign up to request clarification or add additional context in comments.

2 Comments

The question is why do they need the lazy instantiation? The second method could be _factory = (IControllerFactory)Activator.CreateInstance(controllerFactoryType); I've updated the question to be clearer
@JontyMC, you're absolutely right, I missed that nuance before. After examining the source code a bit more, I believe the explanation for the design is to allow implementors of IControllerFactory to maintain state for a specific Controller that it instantiates. i.e. The design results in a 1-1 mapping between instances of a Controller and instances of their IControllerFactory. This way, the implementation of IControllerFactory could, for example, hang on to the instance of the Controller it instantiates in a field for later use. (not sure why you would want to though)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.