是否有办法在接口中指定已知的返回类型,但未知数量/类型的参数。
我问的原因是我使用的是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();
}
}
答案 0 :(得分:3)
您可以尝试使用非常通用的界面。例如:
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
的类的构造函数。 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;
}
}
这样做的好处是,无论何时创建这些对象,您都知道保存对象的最低要求。它还可以阻止你搞乱那些会改变你的PK和RK的东西。
答案 1 :(得分:2)
您可以定义一个参数,即一个数组。此数组将包含名称/值对,并且可以包含您需要的任意数量。我认为这可以为您提供所需的灵活性。
答案 2 :(得分:2)
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);
答案 3 :(得分:2)
这仍然不会显示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]);
}
}