已知返回类型的 .net 接口,但参数类型/数量未知

本文关键字:类型 参数 未知 返回类型 net 接口 | 更新日期: 2023-09-27 17:56:25

有没有办法在接口中指定已知的返回类型,但参数的数量/类型未知。

问的原因是我使用的是Windows Azure表存储,每个表将具有不同的分区键和行键以及不同的输入值。

我正在创建一个ITableOperations接口,代码将是这样的:

interface ITableOperations<T>
    where T : Azure.AzureTableEntity
{
    // Key specification
    string PartitionKey(/* ? What should go here  */);
    // Key specification
    string RowKey(/* ? What should go here  */);
}

和项目表...对于另一个表,输入参数会有所不同

public class ScheduledItem : ITableOperations<ScheduledPostEntity>
{
    public string PartitionKey(Guid userGuid)
    {
        return userGuid.ToString();
    }
    public string RowKey(DateTime dateScheduled)
    {
        return dateScheduled.ReverseTicks();
    }
}

已知返回类型的 .net 接口,但参数类型/数量未知

你可以尝试有一个非常通用的界面。 例如:

interface ITableOperations<T, P, R>
    where T : Azure.AzureTableEntity
{
    string PartitionKey(P partitionKey);
    string RowKey(R rowKey);
}

然后,您的实现可以是:

public class ScheduledItem : ITableOperations<ScheduledPostEntity, Guid, DateTime>
{
    public string PartitionKey(Guid userGuid)
    {
        return userGuid.ToString();
    }
    public string RowKey(DateTime dateScheduled)
    {
        return dateScheduled.ReverseTicks();
    }
}

编辑:

自从我最初写这个答案以来,看看你的一些评论,你可以从不同的角度来看待它。 创建对象后,PartitionKey 和 RowKey 不会更改,因此我几乎会将这些特定函数从此类中删除,并将其移动到从 AzureTableEntity 继承的类的构造函数中。 例如

public class ScheduledPostEntity : Azure.AzureTableEntity
{
    private Guid _userGuid;
    private DateTime _dateScheduled;
    public ScheduledPostEntity()
    {
        // Needed for deserialisation from Azure Table Storage
    }
    public ScheduledPostEntity(Guid userGuid, DateTime dateScheduled)
    {
        _userGuid = userGuid;
        _dateScheduled = dateScheduled;
    }
    public string PartitionKey
    {
        get { return _userGuid.ToString(); }
        set { _userGuid = Guid.Parse(value); }
    }
    public string RowKey
    {
        get { return _dateScheduled.ReverseTicks(); }
        set { _dateScheduled = value.FromReverseTicks(); }
    }
    // These are functions to avoid them being saved as additional properties
    // in Azure Table Storage.  Sometimes you can get away with them being
    // read only properties, but it depends on the type.
    public DateTime DateScheduled()
    {
        return _dateScheduled;
    }
    public Guid UserGuid()
    {
        return _userGuid;
    }
}

这样做的好处是,无论何时在这些对象上创建,您都知道保存对象的最低要求。 它还可以阻止您弄乱会改变您的 PK 和 RK 的东西。

C# 通过使用 params 关键字支持数组形式的多个参数。

你可以这样做:

interface ITableOperations<T>
    where T : Azure.AzureTableEntity
{
    // Key specification
    string PartitionKey(params object[] data);
    // Key specification
    string RowKey(params object[] data);
}

如果您已经知道参数的替代方法,则可以使用重载。假设您有一个可以接收字符串和/或 Guid 的方法,您可以这样做:

    string PartitionKey(Guid guid);
    string PartitionKey(string str);
    string PartitionKey(Guid guid, string str);

如果使用的是 C# 4,则可以使用可选参数:

    string PartitionKey(Guid guid = default(Guid), string str = null);

您可以定义一个参数,该参数将是一个数组。此数组将包含名称/值对,并且可以根据需要包含任意数量。我认为这会给你带来你正在寻找的灵活性。

这仍然不会向您显示DoStuff的正确参数列表(您只会看到params object[]),但它与您获得的一样灵活。请注意,我已经在实现类中显式实现了该方法,因此如果将"foo"声明为Foo而不是IFoo,则不会在智能感知中看到它。

class Program
{
    static void Main(string[] args)
    {
        IFoo foo = new Foo();
        foo.DoStuff(Guid.NewGuid());
    }
}
public interface IFoo
{
    void DoStuff(params object[] args);
}
public class Foo : IFoo
{
    public void DoStuff(Guid arg)
    {
    }
    void IFoo.DoStuff(params object[] args)
    {
        if (args.Length != 1) throw new ArgumentException("args");
        if (args[0].GetType() != typeof(Guid)) throw new ArgumentException("args");
        DoStuff((Guid)args[0]);
    }
}