已知返回类型的 .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();
}
}
你可以尝试有一个非常通用的界面。 例如:
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]);
}
}