声明与类I don'的C#接口的一致性;t拥有
假设我在第三方库中处理多个类,所有这些类都包含声明与类I don'的C#接口的一致性;t拥有,c#,interface,C#,Interface,假设我在第三方库中处理多个类,所有这些类都包含intid{get;}属性。例如: class A { ... int ID {get;} ... } class B { ... int ID {get;} ... } ID是我正在编写的方法中唯一需要使用的属性,该方法需要引用a或B。我声明了一个接口: interface IHasID { int ID {get;} } 但是调用我的方法时,我不能将A或B视为IHasID 例如,在Sw
intid{get;}
属性。例如:
class A {
...
int ID {get;}
...
}
class B {
...
int ID {get;}
...
}
ID
是我正在编写的方法中唯一需要使用的属性,该方法需要引用a或B。我声明了一个接口:
interface IHasID
{
int ID {get;}
}
但是调用我的方法时,我不能将A
或B
视为IHasID
例如,在Swift中,我可以声明一个符合“协议”(Swift版本的接口)的扩展。我看不出用C#能做到这一点。引用共享属性的不相关类的最接近的方法是什么?不,目前没有这样做的方法。你可以:
- 只需使用动态类型,并以这种方式使用
,而无需在编译时进行类型检查ID
- 将每个库类包装在您自己的实现接口的类中
- 请维护人员添加一个接口
有可能在某个时候将此功能添加到C#。有关详细信息,请参见Mads Torgersen’s,但我怀疑这还有很长的路要走。您可以使用泛型方法和ID选择器,而不是包装类。这里的用法很简单,但该模式在某些情况下很有用
public void MyMethod<T>(T value, Func<T, int> selectId)
{
var id = selectId(value);
}
请注意,尽管它们看起来相同,但两个lambda并不相同
Func
vsFunc
如果您想编写适配器作为解决方案,这是我将类型加入层次结构的典型实现
public abstract class HasIDAdapter : IHasID {
public abstract int ID {get;}
private class AAdapter : HasIDAdapter {
A _a;
public AAdapter(A a) {
_a = a;
}
public override int ID { get => _a.ID; }
}
private class BAdapter : HasIDAdapter {
B _b;
public BAdapter(B b) {
_b = b;
}
public override int ID {get => _b.ID;}
}
public static implicit operator HasIDAdapter(A a) => new AAdapter(a);
public static implicit operator HasIDAdapter(B b) => new BAdapter(b);
}
虽然这类问题会产生,但在使用该接口之前,您仍然需要将
A
或B
转换为hasidapter
,但这可以通过将hasidapter
作为方法参数来实现,或者将A
或B
实例分配给hasidapter
类型的变量,然后再将其传递给IHasID
方法 创建一个具有以下所有功能的通用包装类:
接口的实现IHasID
- 使用
和T
获取ID的构造函数,以及Func
- 包装值的getter
class HasId<T> : IHasId {
private readonly Func<T,int> idGetter;
public Value {get;}
public Id => idGetter(Value);
public HasId(T val, Func<T,int> idGetter) {
Value = value;
this.idGetter = idGetter;
}
}
类HasId:IHasId{
私有只读函数idGetter;
公共值{get;}
public Id=>idGetter(值);
公共HasId(T val,Func idGetter){
价值=价值;
this.idGetter=idGetter;
}
}
另一个(并非最佳)解决方案是使用反射:
static int IdOf<T>(T t)
{
return (int)typeof(T).GetProperty("ID").GetValue(t);
}
static int IdOf(T)
{
返回(int)typeof(T).GetProperty(“ID”).GetValue(T);
}
我真的不喜欢这个解决方案,但我还是加入了它,因为它是一个选项…为什么不让你的方法重载呢?我想到的第一件事是围绕
a
和B
创建一个包装类,就像IHasID
的适配器一样。你甚至可以有一个类,每个类型都有一个方法,并使用方法组转换,让类型推断处理它:Foo(newa(),IdExtractor.ExtractId);Foo(新的B(),IdExtractor.ExtractId)代码>您可以展开您的评论吗?我不确定ExtractId
是什么类型。它将是IdExtractor
类中的一组重载方法,例如public int-ExtractId(A){…}public int-ExtractId(B){…}
等。
class HasId<T> : IHasId {
private readonly Func<T,int> idGetter;
public Value {get;}
public Id => idGetter(Value);
public HasId(T val, Func<T,int> idGetter) {
Value = value;
this.idGetter = idGetter;
}
}
static int IdOf<T>(T t)
{
return (int)typeof(T).GetProperty("ID").GetValue(t);
}