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

发布于 2024-11-07 06:10:50 字数 748 浏览 0 评论 0原文

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

我问的原因是我正在使用 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();
    }
}

Is there a way to specify in an interface a known return type, but unknown number/type of parameters.

The reason I am asking is that I am using Windows Azure Table Storage and each table will have different Partition and Row keys with different input values.

I am creating a ITableOperations interface the code will be something like:

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

    // Key specification
    string RowKey(/* ? What should go here  */);
}

And the item table... For another table, the input params would be different

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

能否归途做我良人 2024-11-14 06:10:50

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

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 的事情。

You could try having a very generic interface. For example:

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

    string RowKey(R rowKey);
}

Then your implementation could be:

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

EDIT:

Looking at some of your comments since I originally wrote this answer, you could come at it from a different angle. The PartitionKey and RowKey won't change on your object once it has been created, so I'd almost take these particular functions out of this class and move it to the constructors of the classes that inherit from AzureTableEntity. e.g.

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;
    }
}

This has the advantage that whenever you create on of these objects, you know minimum requirements to save the object. It also stops you from messing with things that will change your PK and RK.

二智少女 2024-11-14 06:10:50

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);

C# supports multiple parameter in the form of an array by using the params keyword.

You could do this:

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

    // Key specification
    string RowKey(params object[] data);
}

If you already know the alternatives of parameters, then you can use overload.
Lets say you have a method that can either receive a string or a Guid or both, you could do this:

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

If you are using C# 4, then you can use optional parameters:

    string PartitionKey(Guid guid = default(Guid), string str = null);
奢望 2024-11-14 06:10:50

您可以定义一个参数,该参数是一个数组。该数组将包含名称/值对,并且可以包含您需要的任意数量。我认为这将为您提供所需的灵活性。

You could define one parameter, which would be an array. This array would contain name/value pairs and could have as many as you need. I think this would give you the flexibility you're looking for.

千仐 2024-11-14 06:10:50

这仍然不会向您显示 DoStuff 的正确参数列表(您只会看到 params object[]),但它已经足够灵活了。请注意,我已在实现类中显式实现了该方法,因此如果“foo”被声明为 Foo 而不是 IFoo,则您不会在 Intellisense 中看到它。

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]);
    }
}

This still won't show you the proper list of parameters for DoStuff (you'll just see params object[]) but it's about as flexible as you'll get. Note that I've implemented the method explicitly in the implementing class so you don't see it in Intellisense if "foo" is declared as a Foo rather than an 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]);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文