这是一个由两部分组成的问题。首先,这些显式属性实现中的哪一个绑定到IAllTogether.SomeInt
,为什么编译器不抱怨模糊性?当您注释掉标记的行时,它会这样做。
public interface IFirst
{
int SomeInt { get; }
}
public interface ISecond
{
int SomeInt { get; }
}
public interface ICombined : IFirst, ISecond
{
new int SomeInt { get; } // Comment this line.
}
public interface IAllTogether : IFirst, ISecond, ICombined
{ }
public sealed class Implementation : IAllTogether
{
int ICombined.SomeInt { get { return 0; } } // Comment this line.
int IFirst.SomeInt { get { return 0; } }
int ISecond.SomeInt { get { return 0; } }
}
IAllTogether t = new Implementation();
var unimportant = t.SomeInt;
第二个问题是:在给定接口PropertyInfo
和属性名称时,如何找到正确的Type
?我可以使用GetInterfaces()
和GetProperty()
列出所有可能的候选人,但我怎么知道哪个是正确的?我试过了typeof(IAllTogether).GetProperty("SomeInt")
,但它不起作用。
看起来第一部分的答案是隐藏继承成员可以解决歧义问题。但是,第二部分甚至还没有一条评论:如何为某些属性名称和接口类型可靠地找到正确的PropertyInfo
。
澄清问题的第二部分。我正在寻找的是为任何未知Type
获取正确属性的方法。基本上,这样的方法:
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (!interfaceType.IsInterface)
throw new ArgumentException();
// for interfaceType == typeof(IAllTogether), return ICombined.SomeInt
// for interfaceType == typeof(IFirst), return IFirst.SomeInt
}
答案 0 :(得分:1)
很多人回答了第一部分:如果某个界面隐藏了原始界面的成员,则不会考虑这些界面。
使用这些信息,这是我在第二部分的尝试。欢迎提出有关问题或改进的评论。
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (interfaceType == null)
throw new ArgumentNullException("interfaceType");
if (!interfaceType.IsInterface)
throw new ArgumentException(
string.Format("Type {0} doesn't represent an interface.",
interfaceType.FullName),
"interfaceType");
// If declared in given interface, just return that.
var declaredProperty = interfaceType.GetProperty(propertyName);
if (declaredProperty != null)
return declaredProperty;
// Otherwise, first finding all the candidates.
var candidates = new HashSet<PropertyInfo>(
interfaceType.GetInterfaces().Select(t => t.GetProperty(propertyName)));
candidates.Remove(null);
if (candidates.Count == 0)
throw new ArgumentException(
string.Format("Property {0} not found in interface {1}.",
propertyName, interfaceType.FullName),
"propertyName");
// Finally, removing all candidates the first candidates hide.
var originalCandidates = candidates.ToList();
candidates.ExceptWith(
originalCandidates.SelectMany(prop => prop.DeclaringType.GetInterfaces())
.Select(t => t.GetProperty(propertyName)));
if (candidates.Count != 1)
throw new AmbiguousMatchException(
string.Format("Property {0} is ambiguous in interface {1}.",
propertyName, interfaceType.FullName));
return candidates.First();
}
答案 1 :(得分:0)
回答你的第一个问题。
编译器只需知道接口成员是否已实现。运行时决定要调用的成员版本。
在您的示例中,您使用的是显式实现。
在这种情况下,编译首先检查是否实现了SomeInt
属性。如果这是隐含的实施,它就不会抱怨。如果显式实现了任何一个接口属性,编译器将检查接口属性是否通过隐式或显式实现。