Unity и ASP.NET WebForms - для этого объекта не определен конструктор без параметров

У кого-нибудь есть хорошие примеры того, как заставить Unity 1.2 или 2.0 работать с ASP.NET WebForms?

Я думал, что понял это, но, очевидно, я что-то упустил. Теперь я получаю ошибку; Msgstr "Для этого объекта не определен конструктор без параметров". Я помню, как получил эту ошибку пару лет назад, и я просто не помню, что я сделал.

Очевидно, что Unity не работает должным образом, потому что где-то по пути я кое-что забыл. Любая помощь будет оценена.

Вот часть моего кода:

Global.asax

используя Систему;
using System.Collections.Generic;
использование System.Linq;
использование System.Web;
использование System.Web.Security;
using System.Web.SessionState;

используя Microsoft.Practices.Unity;

используя PIA35.Unity;

пространство имен PIA35.Web
{
    открытый класс Global: System.Web.HttpApplication
    {

        защищенный void Application_Start(отправитель объекта, EventArgs e)
        {
            IUnityContainer container = Application.GetContainer();
            PIA35.Web.IoC.Bootstrapper.Configure(контейнер);
        }
    }
}

Вот мой раздел httpModules файла web.config:

  

Вот код для моего класса загрузчика IoC.

используя Систему;
using System.Collections.Generic;
использование System.Linq;
использование System.Web;
используя Microsoft.Practices.Unity;

использование PIA35.Services.Interfaces;
используя PIA35.Services;
использование PIA35.DataObjects.Interfaces;
использование PIA35.DataObjects.SqlServer;

пространство имен PIA35.Web.IoC
{
    открытый статический класс Bootstrapper
    {
        public static void Configure(контейнер IUnityContainer)
        {
            контейнер.RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType().RegisterType();
        }
    }
}

Вот файл HttpApplicationStateExtensions.cs.

использование System.Web;

используя Microsoft.Practices.Unity;

Пространство имен PIA35.Unity
{
    открытый статический класс HttpApplicationStateExtensions
    {
        приватная константная строка GlobalContainerKey = "GlobalUnityContainerKey";

        public static IUnityContainer GetContainer(это приложение HttpApplicationState)
        {
            application.Lock();
            пытаться
            {
                IUnityContainer container = application[GlobalContainerKey] as IUnityContainer;
                if (container == null)
                {
                    container = new UnityContainer();
                    application[GlobalContainerKey] = контейнер;
                }
                возвратный контейнер;
            }
            в конце концов
            {
                application.UnLock();
            }
        }
    }
}

Вот мой файл UnityHttpModule.cs.

используя Систему; using System.Collections.Generic; использование System.Web; использование System.Web.UI; используя Microsoft.Practices.Unity;

namespace PIA35.Unity
{открытый класс UnityHttpModule: IHttpModule
    {
        #region Члены IHttpModule /// /// Инициализирует модуль и подготавливает его для обработки запросов. /// /// /// ///, который предоставляет доступ к методам, свойствам, /// и событиям, общим для всех объектов приложения в приложении ASP.NET public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
        }

        ///
        /// Удаляет ресурсы (кроме памяти) ///, используемые модулем, который реализует.
        ///
        ///
        public void Dispose()
        {
        }

        #endregion

        private void OnPreRequestHandlerExecute(отправитель объекта, EventArgs e)
        {
            IHttpHandler handler = HttpContext.Current.Handler;
            HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), обработчик); // Пользовательские элементы управления готовы к созданию после завершения инициализации страницы Page page = HttpContext.Current.Handler as Page;
            if (page!= null)
            {
                page.InitComplete += OnPageInitComplete;
            }
        }

        // Получить элементы управления в дереве элементов управления страницы, исключая саму страницу private IEnumerable GetControlTree(Control root)
        {
            foreach (дочерний элемент управления в root.Controls)
            {
                yield return child;
                foreach (элемент управления c в GetControlTree(child))
                {
                    yield return c;
                }
            }
        }

        // Создаем каждый элемент управления в дереве элементов управления страницы. Void OnPageInitComplete(object sender, EventArgs e)
        {
            Page page = (Page)sender;
            IUnityContainer container = HttpContext.Current.Application.GetContainer();
            foreach (Элемент управления c в GetControlTree(page))
            {
                container.BuildUp(c.GetType(), c);
            }
        }
    }
}

Вот пример одного из моих классов обслуживания.

Пространство имен PIA35.Услуги
{
    открытый класс CategoryService: ICategoryService
    {

        #region Dependency Injection

        частный ICategoryDao CategoryDao;

        public CategoryService(ICategoryDao CategoryDao)
        {
            this.categoryDao = CategoryDao;
        }

        #endregion


        #region ICategoryService Участники

        публичный список GetAll()
        {
            возвращать categoryDao.GetAll().ToList();
        }

        общедоступная категория GetById(int CategoryId)
        {
            вернуть categoryDao.GetById(CategoryId);
        }

        public void Add(модель категории)
        {
            categoryDao.Insert(модель);
        }

        публичное обновление void (модель категории)
        {
            categoryDao.Update(модель);
        }

        public void Удалить (модель категории)
        {
            categoryDao.Delete(модель);
        }

        #endregion
    }
}

3 ответа

Решение

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

Чтобы привести это в порядок, вы можете сделать двойную проверку блокировки. как это:

    public static IUnityContainer GetContainer(this HttpApplicationState application)
    {
        IUnityContainer container = application[GlobalContainerKey] as IUnityContainer;
        if (container == null)
        {
            application.Lock();
            try
            {
                container = application[GlobalContainerKey] as IUnityContainer;
                if (container == null)
                {
                    container = new UnityContainer();
                    application[GlobalContainerKey] = container;
                }
            }
            finally
            {
                application.UnLock();
            }
        }
        return container;
    }

Я также хотел бы указать на аккуратный шаблон, который мы использовали, чтобы убедиться, что элементы управления и страницы имеют свои зависимости. У нас в основном есть Generic PageBase и Generic ControlBase, от которых наследуются все наши страницы и элементы управления. Я просто зайду в базу данных в качестве примера:

public abstract class SitePageBase<T> : SitePageBase where T : SitePageBase<T>
{
    protected override void OnInit( EventArgs e )
    {
        BuildUpDerived();
        base.OnInit( e );
    }

    protected void BuildUpDerived()
    {
        ContainerProvider.Container.BuildUp( this as T );
    }
}

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

public partial class Default : SitePageBase<Default>
{
        [Dependency]
        public IContentService ContentService { get; set; }

        protected override void OnPreRender( EventArgs e )
        {
            this.label.Text = ContentService.GetContent("labelText");
        }
     }

ObjectDataSource может принимать интерфейс, но не с помощью мастера. Вы можете использовать мастер для создания тега ObjectDataSource, затем отредактировать его и превратить значение атрибута TypeName в имя вашего интерфейса.

Затем вам нужно указать ObjectDataSource, как создать объект. Я использую способ обработки события OnObjectCreating, поэтому в приведенном ниже коде я имею:

[Dependency]
public IMyService Service { get; set; }

protected void OnObjectCreating(...)
{
   e.ObjectInstance = Service;
}

У меня был рабочий проект некоторое время назад, и я начал новый проект и получил ту же проблему. Сделайте некоторое сравнение и заняло у меня некоторое время. Но я вспомнил, что вам нужно инициализировать его в global.asax.

Bootstrapper.Initialise(); // Missing in the global.asax
Другие вопросы по тегам