MEF 是否为 Singleton 模式带来任何价值?
我正在开展一个 MEF 项目,以发现使用和实施技术。我的发现的第一阶段是实现一个动态可配置的集中式数据控制器。自定义行为的一种方法是继承我提供的强制执行奇点规则的类。虽然单例模式在使用中饱受诟病,但我可能已经找到了一种实现,可以在某种程度上验证该模式的存在。
情况
假设主机导入的数据控制模块(DataController)旨在根据兄弟模块的请求向数据库提供公共管道。我只需要一个DataController,并且要组成一个模块,DataController必须实现IDataController。将 DataProvider 实现为基类完全是可选的;但是,从 DataProvider 派生将需要一些额外的处理。
观察
收集事实:
静态类不能实现或 扩展抽象类或 接口。仅凭这个事实 消除了静态类的使用 确保一个单一的存在 DataController。
数据控制器实现 单例模式将确保 每个应用程序单一存在 领域。没有限制 数据控制器;允许继承 需要导入的接口以及 在主机中组成。
给定 DataController 的派生, 标准实施 单例模式可能被证明是 在相同的情况下具有挑战性。这 建议的数据库同时提供 公开访问的课程: IDataController 和抽象 数据提供者。为保证单 派生的 DataController 的实例, 实施将需要一些 偏离标准。
解决方案
至此,解决方案似乎很清楚了。通过 DataHandler 基类实现 Singleton 模式。我还没有天真地认为还有其他方法可以做到这一点。但这里是我对如何实现该模式的粗略期望:
// DataLibrary referenced by Host
public interface IDataController
{
IDataController Start();
DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection;
}
public abstract class DataProvider
{
// singleton implementation
private static IDataController dcInstance;
protected static IDataController Instance
{
get{ return dcInstance; }
}
// ========================
abstract IDataController CreateController();
protected IDataController instanceController<TDataController>()
where TDataController : IDataController, new()
{
return new TDataController ();
}
}
// references DataLibrary
[Export(typeof(IDataController))]
public class DataController : DataProvider, IDataController
{
public IDataController Start()
{
return CreateController();
}
protected override IDataController CreateController()
{
return instanceController<DataController>();
}
public SqlConnection CreateConnection(params string[] args)
{
// instance and return new SqlConnection
}
}
请记住,我一直在解决这个问题 - 阅读、理论化 - 但尚未完成实现。当我调试任何问题时,很可能会有一些更新。
显然,只有当 DataController 模块继承抽象基类 DataProvider 时,才会强制执行此实现。因此,如果开发人员选择从 DataProvider 派生 DataController,我们理所当然应该强制执行单一性规则,以避免滥用或误用。
尽管如此,我很好奇是否有比我设计的更容易接受或更实际的实现。而且,我开始质疑单例模式是否是正确的选择。由于单例模式的存在饱受诟病(而且,在大多数情况下,这是理所当然的),因此,我应该质疑我的选择。
是否有更实际的实现来满足我的要求? *在这种情况下,这是单例模式的正确实现吗?* 这个实现实际上对模式的存在有任何价值吗?
I am working on an MEF project to discover usage and implementation techniques. My first phase of discovery is to implement a dynamically configurable and centralized data controller. One way to customize behavior is to inherit a class I provide that enforces a singularity rule. While the Singleton pattern is much maligned in it's use, I may have found an implementation that could validate, to some degree, the pattern's struggling existence.
The Situation
Suppose a data control module (DataController) imported by the Host is intended to supply a common conduit to databases on request by sibling modules. I only need one DataController and to be composed as a module, DataController must implement IDataController. Implementation of DataProvider as the base class is purely optional; however, derivation from DataProvider will require some additional handling.
The Observations
Gathering the facts:
A static class cannot implement or
extend abstract classes or
interfaces. This fact alone
eliminates the use of a static class
to ensure a singular existence of a
DataController.A DataController implementing the
Singleton pattern would ensure a
singular existence per application
domain. There is no restriction on
the DataController; allowed to inherit the
required interface to be imported and
composed in the Host.Given derivation of DataController, the
standard implementation for the
Singleton pattern may prove to be
challenging in same cases. The
proposed data library provides both
publicly accessible classes:
IDataController, and an abstract
DataProvider. To ensure a single
instance of the derived DataController,
the implementation will require some
deviation from the norm.
The Solution
At this point, the solution seems clear. Implementation of the Singleton pattern by the DataHandler base class. I am not naive enough to think that there are other ways I could do this. But here is my rough expectations on how to implement the pattern:
// DataLibrary referenced by Host
public interface IDataController
{
IDataController Start();
DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection;
}
public abstract class DataProvider
{
// singleton implementation
private static IDataController dcInstance;
protected static IDataController Instance
{
get{ return dcInstance; }
}
// ========================
abstract IDataController CreateController();
protected IDataController instanceController<TDataController>()
where TDataController : IDataController, new()
{
return new TDataController ();
}
}
// references DataLibrary
[Export(typeof(IDataController))]
public class DataController : DataProvider, IDataController
{
public IDataController Start()
{
return CreateController();
}
protected override IDataController CreateController()
{
return instanceController<DataController>();
}
public SqlConnection CreateConnection(params string[] args)
{
// instance and return new SqlConnection
}
}
Keep in mind that I have been working this out - read, theorizing - and have not completed the implementation. There will most likely be some updates as I debug any issues.
Obviously, this implementation is only enforced if the DataController module inherits the abstract base class, DataProvider. Therefore, it stands to reason that we should enforce a rule of singularity to avoid abuse or misuse if the developer opts to derive a DataController from DataProvider.
All that said, I am curious if there is a more acceptable, or practical implementation than what I have devised. And, I begin to question if the Singleton pattern is the right choice. With the Singleton pattern's much maligned existence (and, for the most part, rightfully so), I should, therefore, question my choice.
Is there a more practical implementation to meet my requirements?
*Is this the right implementation of the Singleton pattern in this case?*
Does this implementation actually lend any value to the pattern's existence?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果你想强制容器中只存在一个类的实例,那么你可以设置“共享”部件创建策略:
每个导入
IDataController
的部件将接收相同的实例。请注意,如果您在导入或导出端未指定零件创建策略,则这已经是 MEF 中的默认行为。您不应该将“单例性”构建到类中。某个东西是否是单例是组件元数据或容器配置的一部分。其他依赖注入容器也遵循相同的方法。例如,在 autofac 中,您将某些内容声明为单例,如下所示:
If you want to enforce the fact that only a single instance of a class exists in the container, then you can just set the "shared" part creation policy:
Each part importing
IDataController
will then receive the same instance. Note that this already the default behavior in MEF if you specify no part creation policy at the import or export side.You should not build "singletonness" into a class. Whether something is a singleton is part of the component metadata or the configuration of the container. Other dependency injection containers follow the same approach. For example, in autofac you declare something as being a singleton like this:
除非您有更多来自 DataProvider 的所有派生类共享的实现代码,否则您可能只想删除抽象类。此实现保证线程安全并使用惰性构造而不使用锁。但是,需要 .NET 4。
Unless you have more implementation code that all derived classes from DataProvider would share, you might want to simply do away with your abstract class. This implementation guarantees thread-safey and uses lazy construction without the use of locks. However, requires .NET 4.