C# MEF对单例模式有什么价值吗?

C# MEF对单例模式有什么价值吗?,c#,singleton,mef,C#,Singleton,Mef,我正在从事一个MEF项目,以发现使用和实现技术。我发现的第一个阶段是实现一个动态可配置的集中式数据控制器。自定义行为的一种方法是继承我提供的强制执行奇点规则的类。虽然Singleton模式在使用上受到了极大的诽谤,但我可能已经找到了一个实现,可以在某种程度上验证该模式的存在 形势 假设由主机导入的数据控制模块(DataController)旨在根据同级模块的请求向数据库提供公共管道。我只需要一个DataController,要组成一个模块,DataController必须实现IDataContr

我正在从事一个MEF项目,以发现使用和实现技术。我发现的第一个阶段是实现一个动态可配置的集中式数据控制器。自定义行为的一种方法是继承我提供的强制执行奇点规则的类。虽然Singleton模式在使用上受到了极大的诽谤,但我可能已经找到了一个实现,可以在某种程度上验证该模式的存在

形势 假设由主机导入的数据控制模块(DataController)旨在根据同级模块的请求向数据库提供公共管道。我只需要一个DataController,要组成一个模块,DataController必须实现IDataController。DataProvider作为基类的实现是完全可选的;然而,从DataProvider派生将需要一些额外的处理

观察结果 收集事实:

  • 静态类无法实现或 扩展抽象类或 接口。仅此一项事实 消除了静态类的使用 以确保一个 数据控制器

  • 实现 单例模式将确保 每个应用程序的奇异存在性 域名。没有限制 数据控制器;允许继承 需要导入的接口和 在主人面前镇定自若

  • 给定DataController的派生 标准实施 单例模式可能被证明是正确的 在同样的情况下具有挑战性。这个 建议的数据库提供了 可公开访问的类: IDataController和一个摘要 数据提供者。确保单一 派生DataController的实例, 实施将需要一些时间 偏离规范

解决方案 在这一点上,解决方案似乎是明确的。DataHandler基类实现单例模式。我还没有天真到认为还有其他方法可以做到这一点。但以下是我对如何实施该模式的粗略期望:

// 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 
    }
}
//主机引用的数据库
公共接口IDataController
{ 
IDataController启动();
DbConnection CreateConnection(参数字符串[]args)
其中TDbConnection:DbConnection,IDbConnection;
}
公共抽象类数据提供者
{
//单例实现
私有静态IDataController dcInstance;
受保护的静态IDataController实例
{
获取{return dcInstance;}
}
// ========================
抽象IDataController CreateController();
受保护的IDataController实例控制器()
其中TDataController:IDataController,new()
{
返回新的TDataController();
}
}
//参考数据库
[导出(类型(IDataController))]
公共类DataController:DataProvider、IDataController
{
公共IDataController启动()
{
返回CreateController();
}
受保护的覆盖IDataController CreateController()
{
返回instanceController();
}
公共SqlConnection CreateConnection(参数字符串[]args)
{
//实例并返回新的SqlConnection
}
}
请记住,我一直在研究这个问题——阅读、理论——但还没有完成实现。当我调试任何问题时,很可能会有一些更新

显然,只有DataController模块继承抽象基类DataProvider时,才强制执行此实现。因此,如果开发人员选择从DataProvider派生DataController,我们应该强制执行奇点规则,以避免滥用或误用

综上所述,我很好奇是否有比我所设计的更可接受或更实际的实现。而且,我开始质疑单例模式是否是正确的选择。由于单身模式的存在备受诟病(而且在大多数情况下,这是理所当然的),因此,我应该质疑我的选择

是否有更实际的实现来满足我的要求? *在这种情况下,这是单例模式的正确实现吗*
这个实现是否真的有助于该模式的存在?

除非您有更多的实现代码,来自DataProvider的所有派生类都将共享这些代码,否则您可能只想删除抽象类。这个实现保证了线程的安全性,并且在不使用锁的情况下使用惰性构造。但是,需要.NET4

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();
    }
}
公共接口IDataController
{
DbConnection CreateConnection(参数字符串[]args)
其中TDbConnection:DbConnection,IDbConnection;
}
[导出(类型(IDataController))]
公共类数据控制器:IDataController
{
//单例实现
私有静态volatile Lazy _ControllerInstance=new Lazy(()=>new DataController());
公共静态IDataController控制器状态
{
获取{return\u ControllerInstance.Value;}
}
公共数据库连接CreateConnection(参数字符串[]args)
其中TDbConnection:DbConnection,IDbConnection
{
抛出新的NotImplementedException();
}
}

如果要强制执行容器中只存在一个类实例的事实,则可以设置“共享”零件创建策略:

[Export(typeof(IDataController))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class DataController : IDataController
{
    ...
}
导入
IDataController
的每个部件都将接收相同的实例。请注意,如果在导入或导出端未指定零件创建策略,则这已经是MEF中的默认行为

您不应该将“singletoness”构建到类中。组件元数据或容器配置的一部分是单例。其他依赖项注入容器遵循相同的方法。例如,在autofac中,您将某些内容声明为单例,如下所示:

builder.Register(c => new DataController())
    .As<IDataController>().SingleInstance();
builder.Register(c=>newdatacontroller())
.As().SingleInstance