Ideatryout:类型化的Providerfactory
这几天我一直在考虑在 C#.NET (4.0RC) 中启动一个新项目。该项目的最终结果将是一个类库,其中包含我现在所说的“ProviderFactory”、几个接口(或抽象类)和一个或两个默认的“ProviderType”。
首先,我可能需要/决定更改我的类的命名,以免与 .NET 中已有的内容发生冲突。其次,我在这里描述的内容很可能已经存在(甚至可能在我不知道的情况下就存在于 .NET 中),因此如果是这种情况,那么指向该项目或教程的单个链接将不胜感激。
我正在考虑的功能不仅仅是一个可以为我提供简单Provider的工厂,而应该能够生成任何类型的Provider。我希望能够编写这样的内容:
BlogProvider bp = ProviderFactory.GetProvider<BlogProvider>();
并且它应该返回当前选定的 BlogProvider,如果没有则返回 null。另外,我希望能够提供一种类型的所有可用提供程序的列表,例如,
string[] blogproviders = ProviderFactory.GetRegisteredProviders<BlogProvider>();
它应该返回带有博客提供程序的字符串数组(如“ODBCBlogProvider”、“XMLBlogProvider”等)。我还需要能够设置当前的提供程序,例如这样:
ProviderFactory.SetCurrentProvider<BlogProvider>("ODBCBlogProvider");
这应该使当前的 BlogProvider 成为 ODBCBlogProvider,以便下次我调用 ProviderFactory.GetProvider() 时,它应该返回 ODBCBlogProvider 的实例(因此需要扩展 BlogProvider 基类)。
此外,每个 ProviderType(或 ProviderBase,如果您愿意)都需要有一个 ProviderTypeName (BlogProvider) 和一个对该 ProviderType 唯一的 ProviderTypeDisplayName(“博客”或“博客提供程序”),并且扩展该提供程序的每个提供程序都需要有一个ProviderName (ODBCBlogProvider) 和 ProviderDisplayName(“ODBC”或“ODBC 博客”等)。为了简单起见,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 的另一个要求是它应该在无状态环境和保持活动的环境中都工作,因此它应该能够将设置保存到某些配置文件/流/数据库(类似的东西,不并不重要)在初始化时进行更改和加载,但这应该是可选的。因此它也可以在网络上运行(在你自己的机器上拥有一个博客并没有多大意义)。
另一项要求是提供者可能要求其他提供者才能工作。例如,AudiEngine 可能只能与 AudiCar 配合使用,但 AudiCar 可以与 BmwEngine 完美配合。
另外(我不确定该把它放在哪里,也许是提供者类本身的一个可选属性)每个提供者都应该可以选择是否是单例。
目前我能想到的就是这些。任何有关如何实现这一点或是否已经有实现的意见都将不胜感激,并且任何内容都可以更改,因为我还没有编写任何代码,这就是我现在一直在考虑的事情。
I've been thinking about starting a new project in C#.NET (4.0RC) for a couple of days now. The end result of the project would be a class-library consisting of what I for now call a "ProviderFactory", a couple of interfaces (or abstract classes) and a default "ProviderType" or two.
First of all I might need/decide to change the naming of my classes not to clash with what's already in .NET. Secondly it's a good chance that what I'm describing here already exists (it might even be within .NET natively without me knowing about it), so if that's the case a single link to that project or a tutorial would be appreciated.
The functionality I'm thinking about is not just a factory that can provide me with a simple Provider, but it should be able to generate any kind of Provider. I want to be able to write something like this:
BlogProvider bp = ProviderFactory.GetProvider<BlogProvider>();
and it should return the current selected BlogProvider, or null if there is none. Also I want to be able to provide a list over all the available providers of one type like for instance
string[] blogproviders = ProviderFactory.GetRegisteredProviders<BlogProvider>();
and it should return an array of strings with blog-providers (like "ODBCBlogProvider", "XMLBlogProvider", etc.). I also need to be able to set the current provider, for instance like this:
ProviderFactory.SetCurrentProvider<BlogProvider>("ODBCBlogProvider");
This should make the current BlogProvider the ODBCBlogProvider, so that next time I call ProviderFactory.GetProvider() it should return an instance of ODBCBlogProvider (which of cause need to extend the BlogProvider base class).
Also, every ProviderType (or ProviderBase if you like) needs to have a ProviderTypeName (BlogProvider) and a ProviderTypeDisplayName ("Blog" or "Blog provider") that is unique to that ProviderType, and every Provider that extends that provider needs to have a ProviderName (ODBCBlogProvider) and a ProviderDisplayName ("ODBC" or "ODBC blog" etc.). The ProviderName and ProviderTypeName could just for simplicity be there class-names gained by reflection.
This probably means that I'd need an interface for the ProviderBase, something like this:
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."
}
And for the BlogProvider I'd need to create a abstract class that implements those two members and creates methods for the actual BlogProviders to override.
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();
}
Then, somewhere in my code I'd had to run something like
ProviderFactory.RegisterProviderType(typeof(BlogProvider));
or an even better option would be to be able to use attributes like this:
[Provider("Blog", "This provides you with a blog.")]
public interface BlogProvider
{
int GetPostCount();
}
I don't see the need to use an abstract class with this approach because none of the members needs to be set in the base class. Also the need for the ProviderBase-interface is gone. The ideal thing would of cause be if the ProviderFactory could just find all the classes/interfaces containing the ProviderAttribute, and than ODBCBlogProvider would just need to implement BlogProvider, but I'm not certain how I do this, especially not when it's a requirement that the providers and providertypes can both come for external assemblies.
Another requirement of the ProviderFactory is that it should work both when in a stateless environment and in a environment where it is kept alive, thus it should be able to save settings to some config-file/stream/database (something like that, doesn't really matter) on change and load from this at initialization, but this should be optional. Thus it would also work on the web (having a blog on your own machine doesn't give too much sense).
One more requirement is that the Providers might require other Providers to work. For instance, and AudiEngine might only work with an AudiCar, however an AudiCar can run perfectly with an BmwEngine.
Also (and I'm not sure where to put that yet, maybe an optional attribute on the provider-class itself) every provider should have the option to be singleton or not.
That is all I can think of for now. Any input on how this should be implemented or weather there already is a implementation out there would be greatly appreciated, and anything can be changed because I haven't written any code yet, this is all something I've been thinking about for now.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
嗯,它看起来像是一个过度设计的(更确切地说,过于花哨的命名)IoC/DI 容器。
IoC 的想法几乎相同,除了它们(容器)不需要您的“协作者”实现任何接口或从基类派生:
这是一个使用 autofac,它是用于 C#/.NET 的众多 DI 容器之一。
Well, it looks like an overengineered (rather, overly-fancy-named) IoC/DI container.
The idea of IoC is pretty much the same, with the exception that they (containers) do not require your "collaborators" to implement any interfaces or derive from base classes:
This is an example using autofac, which is one of a myriad of DI containers for C#/.NET.
正如@Anton 所指出的,这接近于 IoC/DI 容器。同样,使用 Autofac,您可以做如下的事情:
As @Anton indicates, this is close to a IoC/DI container. Again, using Autofac, you can get a long way doing something like this: