2

几天来,我一直在考虑在 C#.NET (4.0RC) 中启动一个新项目。该项目的最终结果将是一个类库,其中包含我现在称之为“ProviderFactory”的东西、几个接口(或抽象类)和一个或两个默认的“ProviderType”。

首先,我可能需要/决定更改我的类的命名,以免与 .NET 中已有的内容发生冲突。其次,我在这里描述的内容很有可能已经存在(它甚至可能在我不知道的情况下本机在 .NET 中),所以如果是这种情况,将不胜感激单个链接到该项目或教程。

我正在考虑的功能不仅仅是一个可以为我提供简单Provider的工厂,它应该能够生成任何类型的Provider。我希望能够写出这样的东西:

BlogProvider bp = ProviderFactory.GetProvider<BlogProvider>();

它应该返回当前选择的 BlogProvider,如果没有,则返回 null。此外,我希望能够提供一种类型的所有可用提供者的列表,例如

string[] blogproviders = ProviderFactory.GetRegisteredProviders<BlogProvider>();

它应该返回一个带有博客提供者的字符串数组(如“ODB​​CBlogProvider”、“XMLBlogProvider”等)。我还需要能够设置当前的提供者,例如这样:

ProviderFactory.SetCurrentProvider<BlogProvider>("ODBCBlogProvider");

这应该使当前的 BlogProvider 成为 ODBCBlogProvider,这样下次我调用 ProviderFactory.GetProvider() 时它应该返回一个 ODBCBlogProvider 的实例(这需要扩展 BlogProvider 基类)。

此外,每个 ProviderType(或 ProviderBase,如果您愿意)都需要有一个 ProviderTypeName (BlogProvider) 和一个 ProviderTypeDisplayName(“博客”或“博客提供者”),该 ProviderType 是唯一的,并且每个扩展该提供者的 Provider 都需要有一个ProviderName (ODBCBlogProvider) 和一个 ProviderDisplayName(“ODBC”或“ODBC blog”等)。为简单起见,ProviderName 和 ProviderTypeName 可以是通过反射获得的类名。

这可能意味着我需要一个 ProviderBase 接口,如下所示:

public interface ProviderBase
{
    string ProviderName { get; } // The display-name.
    string Description { get; } // A description of the provider type, like "This provides you with a blog."
}

对于 BlogProvider,我需要创建一个抽象类来实现这两个成员,并为实际的 BlogProviders 创建方法来覆盖。

public abstract class BlogProvider : ProviderBase
{
    public string ProviderName
    {
        get { return "Blog"; }
    }

    public string Description
    {
        get { return "This provides you with a blog."; }
    }

    public abstract int GetPostCount();
}

然后,在我的代码中的某个地方,我不得不运行类似的东西

ProviderFactory.RegisterProviderType(typeof(BlogProvider));

或者更好的选择是能够使用这样的属性:

[Provider("Blog", "This provides you with a blog.")]
public interface BlogProvider
{
    int GetPostCount();
}

我认为不需要使用这种方法使用抽象类,因为不需要在基类中设置任何成员。也不再需要 ProviderBase 接口。理想的原因是 ProviderFactory 可以找到包含 ProviderAttribute 的所有类/接口,而 ODBCBlogProvider 只需要实现 BlogProvider,但我不确定我是如何做到这一点的,尤其是当它是一个要求时提供者和提供者类型都可以用于外部程序集。

ProviderFactory 的另一个要求是它应该在无状态环境和保持活动状态的环境中都可以工作,因此它应该能够将设置保存到某些配置文件/流/数据库(类似的东西,不t 真的很重要)在初始化时更改和加载,但这应该是可选的。因此它也可以在网络上运行(在您自己的机器上拥有一个博客并没有太大意义)。

另一个要求是提供者可能需要其他提供者才能工作。例如,AudiEngine 可能只能与 AudiCar 一起使用,但 AudiCar 可以完美地与 BmwEngine 一起运行。

另外(我还不确定把它放在哪里,也许是提供者类本身的一个可选属性)每个提供者都应该可以选择是否为单例。

这就是我现在能想到的。任何关于如何实现或天气已经有实现的输入将不胜感激,并且任何东西都可以更改,因为我还没有编写任何代码,这就是我现在一直在考虑的事情。

4

2 回答 2

2

好吧,它看起来像是一个过度设计(相当,过于花哨的名称)的IoC/DI容器。

IoC 的想法几乎相同,除了它们(容器)不需要您的“协作者”来实现任何接口或从基类派生:

var builder = new ContainerBuilder();
builder.Register<Car>();
builder.Register<Engine>().As<IEngine>();

var container = builder.Build();

// somewhere in the code
var car = container.Resolve<Car>();

这是一个使用autofac的示例,它是 C#/.NET 的无数 DI 容器之一。

于 2010-03-09T13:16:04.770 回答
0

正如@Anton 所指出的,这接近于 IoC/DI 容器。同样,使用 Autofac,你可以做这样的事情很长的路要走:

var builder = new ContainerBuilder();
builder.Register<Car>();
builder.Register<BmwEngine>();
builder.Register<AudiEngine>();
builder.Register<DefaultEngine>();
builder.Register<EngineSelector>().As<IEngineSelector>().SingletonScope();

builder.Register(
    c => {
            var selector = c.Resolve<IEngineSelector>();
            switch(selector.CurrentEngine)
            {
                case "bmw":
                    return c.Resolve<BmwEngine>();
                case "audi":
                    return c.Resolve<AudiEngine>();
                default:
                    return c.Resolve<DefaultEngine>();
            }
        }
    ).As<IEngine>().FactoryScoped();

var container = builder.Build();

// somewhere in the code
var selector = container.Resolve<IEngineSelector>();
selector.CurrentEngine = "bmw";

var car = container.Resolve<Car>();
于 2010-03-09T22:01:26.440 回答