Как я могу настроить Factory с возможными провайдерами? - PullRequest
0 голосов
/ 14 апреля 2010

У меня есть три сборки: «Framework.DataAccess», «Framework.DataAccess.NHibernateProvider» и «Company.DataAccess». Внутри сборки "Framework.DataAccess" у меня есть фабрика (с неправильной реализацией открытия):

public class DaoFactory 
{
    private static readonly object locker = new object();
    private static IWindsorContainer _daoContainer;

    protected static IWindsorContainer DaoContainer
    {
        get
        {
            if (_daoContainer == null)
            {
                lock (locker)
                {
                    if (_daoContainer != null)
                        return _daoContainer;

                    _daoContainer = new WindsorContainer(new XmlInterpreter());

                    // THIS IS WRONG! THIS ASSEMBLY CANNOT KNOW ABOUT SPECIALIZATIONS!
                    _daoContainer.Register(
                        AllTypes.FromAssemblyNamed("Company.DataAccess")
                            .BasedOn(typeof(IReadDao<>)).WithService.FromInterface(),
                        AllTypes.FromAssemblyNamed("Framework.DataAccess.NHibernateProvider")
                            .BasedOn(typeof(IReadDao<>)).WithService.Base());                        
                }
            }

            return _daoContainer;
        }
    }

    public static T Create<T>()
        where T : IDao
    {
        return DaoContainer.Resolve<T>();
    }
}

Эта сборка также определяет базовый интерфейс для доступа к данным IReadDao:

public interface IReadDao<T>
{
    IEnumerable<T> GetAll();
}

Я хочу, чтобы эта сборка была общей и без ссылок. Это моя базовая сборка доступа к данным.

Тогда у меня есть сборка провайдера NHibernate, которая реализует вышеупомянутый IReadDao, используя подход NHibernate. Эта сборка ссылается на сборку «Framework.DataAccess».

public class NHibernateDao<T> : IReadDao<T>
{
    public NHibernateDao()
    {
    }

    public virtual IEnumerable<T> GetAll()
    {
        throw new NotImplementedException();
    }
}

Наконец, у меня есть сборка "Company.DataAccess", которая может переопределить реализацию по умолчанию поставщика NHibernate и ссылаться на обе ранее увиденные сборки.

public interface IProductDao : IReadDao<Product> 
{
    Product GetByName(string name);
}

public class ProductDao : NHibernateDao<Product>, IProductDao
{
    public override IEnumerable<Product> GetAll()
    {
        throw new NotImplementedException("new one!");
    }

    public Product GetByName(string name)
    {
        throw new NotImplementedException();
    }
}

Я хочу иметь возможность писать ...

IRead<Product> dao = DaoFactory.Create<IRead<Product>>();

... а затем получите реализацию ProductDao. Но я не могу держать в своей базе данных доступ к какой-либо ссылке на конкретные сборки! Моя первоначальная идея состояла в том, чтобы прочитать это из файла конфигурации xml.

Итак, мой вопрос: как я могу внешне настроить эту фабрику для использования конкретного поставщика в качестве реализации по умолчанию и реализации клиента?

1 Ответ

0 голосов
/ 30 апреля 2010

Понял.

Я использую IWindsorInstaller для реализации пакетов:

public class TestDaoInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            AllTypes.FromAssemblyNamed("Company.DataAccess")
                .BasedOn(typeof(IReadDao<>)).WithService.FromInterface(),
            AllTypes.FromAssemblyNamed("Framework.DataAccess.NHibernate")
                .BasedOn(typeof(IReadDao<>)).WithService.Base());
    }
}

А на Framework.DataAccess мой контейнер теперь:

protected static IWindsorContainer DaoContainer
{
    get
    {
        if (_daoContainer == null)
        {
            lock (locker)
            {
                if (_daoContainer != null)
                    return _daoContainer;

                _daoContainer = new WindsorContainer(new XmlInterpreter());
                IWindsorInstaller[] daoInstallers = _daoContainer.ResolveAll<IWindsorInstaller>();
                foreach (IWindsorInstaller daoInstaller in daoInstallers)
                    _daoContainer.Install(daoInstaller); 

            }
        }

        return _daoContainer;
    }
}
...