我想在C#中创建一个使用Point对象的库,但是在C#中有很多框架都有很多Point的实现:Point,Vector2f(unity),Vector2f(monogame),Vector3f ...我希望我的图书馆可以与所有人一起工作。
唯一的限制是对象具有属性X和Y,并且X和Y必须实现IComparable接口。问题是,如果不使用反射,我就无法找到一种方法(不是我认为最好的方法)。
我不希望所有类Point继承自我的界面,但我希望它们有2个字段/成员X和Y.
有办法吗?像
customersRef.child(u.id!).child(("deals" as NSString)).childByAutoId().setValue("true") { error, dbRef in
print("Is now always called")
}
答案 0 :(得分:2)
您无法在编译时检查它,因为如果您不希望所有类继承公共接口或创建大量适配器,则C#无法满足您的需求。
在运行时,Reflection是您实现目标的唯一方法。反思并不总是那么糟糕,它只取决于你如何实现事物。实际上,反思的第一个问题是表现。
如果您在每次通话中使用它,可能会带来很大的开销。但是,如果你在静态构造函数中检查它,那么检查将只应用一次,并且在标称执行时没有任何开销就可以完成工作。
class MyAlgo<T>
{
static private Func<T, int> X;
static private Func<T, int> Y;
static MyAlgo()
{
//check here!
var type = typeof(T);
var x = type.GetProperty("X");
if (x == null) { throw new NotSupportedException($"missing X property in { type }"); }
var y = type.GetProperty("Y");
if (y == null) { throw new NotSupportedException($"missing Y property in { type }"); }
// you can store delegate to retreive X & Y in static fields.
MyAlgo<T>.X = Delegate.CreateDelegate(typeof(Func<T, int>), x.GetGetMethod());
MyAlgo<T>.Y = Delegate.CreateDelegate(typeof(Func<T, int>), y.GetGetMethod());
}
}
答案 1 :(得分:1)
你在这里谈论的是Duck Typing。 (如果它看起来像一只鸭子,像鸭子那样嘎嘎叫,它一定是鸭子,对吗?)。
C#并不完全支持传统意义上的鸭子打字。大多数强类型编译语言没有此功能(afaik)。但是,正如您在维基百科上看到的那样,您可以使用dynamic
代替。
正如已经提到的,反射实际上是唯一的方式,我理解它的方式dynamic
实际上只是在引擎盖下使用反射。如果表现是一个问题(在这种情况下可能是这样),你应该尝试一些不同的方法和措施。 quick google似乎表明它非常复杂,但至少值得一试。