Мой MVC Custom ControllerFactory работает, но может ли он быть лучше? - PullRequest
2 голосов
/ 27 ноября 2010

Я смотрел на платформы Ninject, StructureMap и Other Dependency Injection и Service Locator, но этот вопрос больше касается изучения того, как это работает и что может быть лучше. Более того, мне не интересно смотреть на исходный код Framework для внедрения зависимостей, но я понимаю, как это достигается от начала до конца на практике / в коде.

Приведенный ниже код предназначен для небольшого внутреннего проекта, поэтому с учетом этого позвольте мне начать.

Вот мой интерфейс для возврата доменных моделей на мои контроллеры. Я решил, что из-за размера проекта (маленького) приемлем был единый интерфейс для контроллеров.

interface IModelFactory
{
    IEnumerable<User> GetUsers();
    User GetUser(Guid UserID);
    bool Add(User User);
    bool Delete(User User);
    bool Update(User User);
    IEnumerable<Car> GetCars();
    Car GetCar(Guid CarID);
    bool Add(Car Car);
    bool Delete(Car Car);
    bool Update(Car Car);
}

Каждый контроллер имеет наследство от DIBaseController, поэтому мне не нужно было создавать закрытые члены для каждого контроллера.

public abstract class DIBaseController : Controller
{
    protected IModelFactory ModelFactory { get; set; }

    public DIBaseController(IModelFactory ModelFactory)
    {
        this.ModelFactory = ModelFactory;
    }
}

public class HomeController : DIBaseController
{
    public HomeController (IModelFactory ModelFactory)
        : base(ModelFactory)
    {
    }
}

Создал мою собственную фабрику контроллеров, которая позволяет мне внедрять мой ModelFactory в контроллеры.

internal class DIControllerFactory : DefaultControllerFactory 
{
    private IModelFactory _ModelFactory;

    internal DIControllerFactory(IModelFactory ModelFactory)
    {
        this._ModelFactory = ModelFactory;
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        IController result = null;
        string thisnamespace = this.GetType().Namespace;
        //This could be improved I bet.
        Type controller = Type.GetType(thisnamespace.Substring(0, thisnamespace.IndexOf('.')) + ".Controllers." + controllerName + "Controller");

        if (controller != null
            && controller.IsSubclassOf(typeof(DIBaseController)))
        {
            result = (IController)Activator.CreateInstance(controller, new object[] { this._ModelFactory });
        }
        else
        {
            result = base.CreateController(requestContext, controllerName);
        }

        return result;
    }
}

И, наконец, добавил код для добавления класса Concreate в Factory для добавления в созданные контроллеры.

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory(new LinqSqlModelFactory()));
    }

Единственная область, которую я не исследовал (и я не думаю, что в данный момент мне это интересно) - это создание раздела web.config для динамического создания ModelFactory. Это работает, но мне интересно, если я полностью пропустил лодку, подойду ближе, или если я на месте?

1 Ответ

4 голосов
/ 28 ноября 2010

Вместо переопределения CreateController используйте

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)

Это дает вам тип контроллера, и первая часть вашей реализации устарела.

Следующее, что вы должны улучшить, это то, что вы анализируете параметры конструктора и передаете экземпляр тех параметров, которые созданы с использованием некоторой конфигурации, вместо того, чтобы предполагать, что существует только один параметр IModelFactory.

...