c# - 没有成员的接口(interface)是否适合向图书馆用户指示 "opaque handle"?

标签 c# .net interface

假设我有一个抽象对象,可以由多个独立的插件作者实现。 (例如,错误数据库连接)我不希望我的位的消费者必须处理每个特定的插件类型。

我还想将解析配置文件的过程与实际初始化数据库插件和其他类似事情的过程分开。

为此,我想到了这样的事情:

public interface IConfiguration
{
    // No members
}

public interface IConnection
{
    // Members go in here
    void Create();
    void Update();
    void Delete();
}

public interface IConnectionProvider
{
    // Try to interpret file as a configuration, otherwise return null
    IConfiguration ParseConfiguration(Stream configurationContents);
    IConnection Connect(IConfiguration settings);
}

public class ThingyRepository
{
    // Lets say there is a constructor that initializes this with something
    List<IConnectionProvider> providers;

    // Insulates people from the actual connection provider
    KeyValuePair<IConfiguration, IConnectionProvider> Parse(string filename)
    {
        IConnection result = null;
        IConnectionProvider resultProvider = null;
        foreach (var provider in this.providers)
        {
            using (Stream fs = OpenTheFileReadonly(filename))
            {
                IConnection curResult = provider.ParseConfiguration(fs);
                if (curResult == null)
                {
                    continue;
                }
                else
                {
                    if (result == null)
                    {
                        result = curResult;
                        resultProvider = provider;
                    }
                    else
                    {
                        throw new Exception ("ambguity!");
                    }
                }
            }
        }

        if (result == null)
        {
            throw new Exception ("can't parse!");
        }

        return new KeyValuePair<IConfiguration, IConnectionProvider>(
            result, resultProvider);
    }
}

我的问题是,我有一个空接口(interface),它应该用作从指定文件加载的任何设置的不透明句柄。 IConnectionProvider 的特定实现者知道它需要从文件加载的配置中的哪些位,但该库的用户应该与该信息隔离。

但是我觉得有一个空的界面似乎很奇怪。这种事情有意义吗?还是我做错了什么?

最佳答案

没有成员的接口(interface)的基本概念,简单地将实现者标识为某物,而不是接口(interface)的正常工作,即标识对象具有或做什么,被称为“标志接口(interface)” .它有它的用途,但要谨慎使用。例如,我通常以分层格式使用它们来识别应该持久保存到特定数据存储的域对象:

//no direct implementors; unfortunately an "abstract interface" is kind of redundant
//and there's no way to tell the compiler that a class inheriting from this base 
//interface is wrong,
public interface IDomainObject
{
   int Id {get;}
}

public interface IDatabaseDomainObject:IDomainObject { }

public interface ICloudDomainObject:IDomainObject { }

public class SomeDatabaseEntity:IDatabaseDomainObject
{
    public int Id{get;set;}

    ... //more properties/logic
}

public class SomeCloudEntity:ICloudDomainObject
{
    public int Id{get;set;}

    ... //more properties/logic
}

派生接口(interface)没有告诉我关于实现对象的结构的任何新信息,除了对象属于那个特定的子域,允许我进一步控制什么可以传递到哪里:

//I can set up a basic Repository pattern handling any IDomainObject...
//(no direct concrete implementors, though I happen to have an abstract)
public interface IRepository<T> where T:IDomainObject
{
    public TDom Retrieve<TDom>(int id) where TDom:T;
}

//... Then create an interface specific to a sub-domain for implementations of
//a Repository for that specific persistence mechanism...
public interface IDatabaseRepository:IRepository<IDatabaseDomainObject>
{
    //... which will only accept objects of the sub-domain.
    public TDom Retrieve<TDom>(int id) where TDom:IDatabaseDomainObject;
}

可以在编译时检查生成的实现及其用法,以证明 ICloudDomainObject 没有传递到 IDatabaseRepository,并且在任何时候都不能将 String 或 byte[] 传递到存储库中进行存储。这种编译时安全性对于特性或属性是不可能的,这是将类“标记”为具有某些特殊意义的其他主要方法。

所以简而言之,这本身不是做法,但一定要问问自己,你想从标志接口(interface)中得到什么,并问问自己是否有任何状态或逻辑数据通常会在IConfiguration(可能是所述配置的名称或其他标识符,或者将其加载或保存到所选数据存储的方法)可以执行一些强制标准化。

关于c# - 没有成员的接口(interface)是否适合向图书馆用户指示 "opaque handle"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14449999/

相关文章:

c# - 在 C# 中测试两个接口(interface)实例之间的值相等性?

c# - ExceptionAggregator.cs 在哪里

.net - 从 DispatcherObject 继承的类是线程安全的还是线程不安全的?

c# - 有没有办法更好地解析字符串?

java - 调用Java接口(interface)方法时的困惑

c# - 如何在 Ninject 中使用策略模式

c# - 如何向我在 vs2010 中发布的项目添加发布日期?

java - 如何获取接口(interface)<T>的返回类型?

C# 如何设置文件夹图标?

javascript - 在传单中实现Ilayer接口(interface)