如何使用可能的提供者配置工厂?

发布于 2024-08-28 20:02:01 字数 2628 浏览 7 评论 0原文

我有三个程序集:“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 提供程序的程序集,它使用 NHibernate 的方法实现上述 IReadDao。该程序集引用“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 配置文件中读取它。

所以,我的问题是:如何从外部配置这个工厂以使用特定的提供程序作为我的默认实现和客户端实现?

I have three assemblies: "Framework.DataAccess", "Framework.DataAccess.NHibernateProvider" and "Company.DataAccess". Inside the assembly "Framework.DataAccess", I have my factory (with the wrong implementation of discovery):

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>();
    }
}

This assembly also defines the base interface for data access IReadDao:

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

I want to keep this assembly generic and with no references. This is my base data access assembly.

Then I have the NHibernate provider's assembly, which implements the above IReadDao using NHibernate's approach. This assembly references the "Framework.DataAccess" assembly.

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

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

At last, I have the "Company.DataAccess" assembly, which can override the default implementation of NHibernate provider and references both previously seen assemblies.

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();
    }
}

I want to be able to write...

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

... and then get the ProductDao implementation. But I can't hold inside my base data access any reference to specific assemblies! My initial idea was to read that from a xml config file.

So, my question is: How can I externally configure this factory to use a specific provider as my default implementation and my client implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

指尖微凉心微凉 2024-09-04 20:02:02

知道了。

我正在使用 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;
    }
}

Got it.

I am using IWindsorInstaller to implement packages:

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());
    }
}

And at Framework.DataAccess, my container is now:

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文