我正在开发一个MEF项目来发现使用和实现技术。我的第一个发现阶段是实现动态可配置和集中的数据控制器。自定义行为的一种方法是继承我提供的强制执行奇点规则的类。虽然Singleton模式在使用中受到很多诽谤,但我可能已经找到了一种可以在某种程度上验证模式存在困难的实现。
假设主机导入的数据控制模块( DataController )旨在根据兄弟模块的请求为数据库提供公共管道。我只需要一个DataController并作为一个模块组成,DataController必须实现IDataController。 DataProvider作为基类的实现纯粹是可选的;但是,从DataProvider派生需要一些额外的处理。
收集事实:
静态类无法实现或 扩展抽象类或 接口。仅这一事实 消除了静态类的使用 确保一个单一的存在 DataController类。
实现的DataController 单身模式将确保一个 每个应用的奇异存在 域。没有限制 DataController;允许继承 要导入的必需接口和 由主持人组成。
给定DataController的派生, 标准实施 单身模式可能被证明是 同样具有挑战性。该 建议的数据库提供两者 可公开访问的类: IDataController和一个抽象 DataProvider的。确保单一 派生的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,我们应该强制执行单一性规则以避免滥用或滥用。
所有这一切,我很好奇是否有比我设计的更可接受或实际的实施。而且,我开始质疑Singleton模式是否是正确的选择。由于Singleton模式存在很多诽谤(并且,大部分情况下都是如此),因此我应该质疑我的选择。
是否有更实际的实施来满足我的要求? *在这种情况下,这是Singleton模式的正确实现吗?* 这种实现是否真的为模式的存在提供了任何价值?
答案 0 :(得分:18)
如果要强制执行容器中只存在一个类的单个实例的事实,那么您只需设置“共享”部件创建策略:
[Export(typeof(IDataController))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class DataController : IDataController
{
...
}
导入IDataController
的每个部分将接收相同的实例。请注意,如果您在导入或导出端未指定任何部件创建策略,则这已经是MEF中的默认行为。
你不应该在课堂上建立“单身”。是否是单例是组件元数据的一部分或容器的配置。其他依赖注入容器遵循相同的方法。例如,在autofac中,您将某些内容声明为像这样的单例:
builder.Register(c => new DataController())
.As<IDataController>().SingleInstance();
答案 1 :(得分:0)
除非您有更多的实现代码,所有来自DataProvider的派生类都会共享,否则您可能只想取消抽象类。此实现保证线程安全并使用惰性构造而不使用锁。但是,需要.NET 4。
public interface IDataController
{
DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection;
}
[Export(typeof(IDataController))]
public class DataController : IDataController
{
// singleton implementation
private static volatile Lazy<IDataController> _ControllerInstance = new Lazy<IDataController>(() => new DataController());
public static IDataController ControllerInstance
{
get { return _ControllerInstance.Value; }
}
public DbConnection CreateConnection<TDbConnection>(params string[] args)
where TDbConnection : DbConnection, IDbConnection
{
throw new NotImplementedException();
}
}