2008-11-10 24 views
19

Cụ thể hơn, nếu tôi có:Làm cách nào để sử dụng phản chiếu để các thuộc tính có thể triển khai giao diện một cách rõ ràng?

public class TempClass : TempInterface 
{ 

    int TempInterface.TempProperty 
    { 
     get; 
     set; 
    } 
    int TempInterface.TempProperty2 
    { 
     get; 
     set; 
    } 

    public int TempProperty 
    { 
     get; 
     set; 
    } 
} 

public interface TempInterface 
{ 
    int TempProperty 
    { 
     get; 
     set; 
    } 
    int TempProperty2 
    { 
     get; 
     set; 
    } 
} 

Làm thế nào để sử dụng phản ánh để có được tất cả các propertyInfos đối với tài sản thực hiện một cách rõ ràng TempInterface?

Cảm ơn.

+0

Bạn có thể làm rõ chính xác những gì bạn đang tìm kiếm không? Bạn có muốn danh sách tất cả các thuộc tính được TempClass triển khai một cách rõ ràng không?Hay bạn chỉ muốn các thuộc tính của TempInterface? ... –

+0

Tôi muốn danh sách tất cả các thuộc tính được thực hiện một cách rõ ràng bởi TempClass –

Trả lời

1

tôi đã phải thay đổi câu trả lời Jacob Carpenter, nhưng nó hoạt động độc đáo. nobugz cũng hoạt động nhưng Jacobs nhỏ gọn hơn.

var explicitProperties = 
from method in typeof(TempClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) 
where method.IsFinal && method.IsPrivate 
select method; 
+0

Câu trả lời của bạn là nhận được các phương pháp, Jacob's đang nhận được các thuộc tính như bạn đã hỏi trong câu hỏi ban đầu. – nawfal

1

Quá phức tạp. Bạn phải phản ánh qua các phương pháp/thuộc tính của loại Giao diện, xem chúng có tồn tại trong loại lớp của bạn không và so sánh chúng để xem chúng có giống nhau không khi chúng tồn tại.

Nếu có thứ gì đó trong giao diện nhưng không phải loại bạn đang thử nghiệm, đó là cách triển khai rõ ràng. Nếu nó ở cả hai, nhưng khác nhau giữa hai, đó là một giao diện rõ ràng.

+0

Nếu một lớp thực hiện một giao diện, nó sẽ thực hiện tất cả các thuộc tính và phương thức trong giao diện đó. Vì vậy, bạn không cần phải kiểm tra các thành viên của lớp, bạn chỉ cần kiểm tra các thành viên của giao diện. –

+0

Bạn phải so sánh các thành viên giao diện với các thành viên của lớp để tìm hiểu xem thành viên có được * thực hiện rõ ràng hay không. – MrKurt

0

đang Jacob thiếu lọc:

 var props = typeof(TempClass).GetInterfaces().Where(i => i.Name=="TempInterface").SelectMany(i => i.GetProperties()); 
     foreach (var prop in props) 
      Console.WriteLine(prop); 
+0

Nếu bạn chỉ muốn thuộc tính giao diện của TempInterfaces, tại sao không bắt đầu với typeof (TempInterface)? –

+1

Vì điều đó đòi hỏi tôi phải thông minh hơn tôi. –

4

Các getter tài sản và setter của một tài sản giao diện thực hiện một cách rõ ràng có một thuộc tính bất thường. Đó là tài sản IsFinal là True, ngay cả khi nó không phải là thành viên của một lớp kín. Hãy thử mã này để xác minh khẳng định của tôi:

foreach (AssemblyName name in Assembly.GetEntryAssembly().GetReferencedAssemblies()) { 
    Assembly asm = Assembly.Load(name); 
    foreach (Type t in asm.GetTypes()) { 
     if (t.IsAbstract) continue; 
     foreach (MethodInfo mi in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)) { 
     int dot = mi.Name.LastIndexOf('.'); 
     string s = mi.Name.Substring(dot + 1); 
     if (!s.StartsWith("get_") && !s.StartsWith("set_")) continue; 
     if (mi.IsFinal) 
      Console.WriteLine(mi.Name); 
     } 
    } 
    } 
+0

Vì vậy, cả hai phương thức get/set sẽ được đánh dấu cuối cùng? Có thể cho một người được và không phải là người khác? cảm ơn. –

+0

Lưu ý việc sử dụng "get_" và "set_" trong đoạn mã –

2

Dưới đây là một giải pháp được sửa đổi dựa trên việc thực hiện đưa ra trong this blog post:

var explicitProperties = 
    from prop in typeof(TempClass).GetProperties(
     BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) 
    let getAccessor = prop.GetGetMethod(true) 
    where getAccessor.IsFinal && getAccessor.IsPrivate 
    select prop; 

foreach (var p in explicitProperties) 
    Console.WriteLine(p.Name); 
+0

Bạn có biết ok nếu giả sử getAccessor isPrivate không? Điều này sẽ luôn luôn đúng? Ngoài ra, cả hai phương thức get/set đều được đánh dấu cuối cùng hoặc là có thể cho một phương thức và không phải là phương thức khác. cảm ơn. –

+0

Khả năng truy cập của cả hai phương pháp sẽ giống nhau đối với một thuộc tính được triển khai rõ ràng. Cả hai phương pháp đều là riêng tư, theo quan điểm của hợp đồng của lớp. –

+0

khi liệt kê explicitProperties tôi nhận được lỗi tham chiếu null. –

19

Tôi nghĩ lớp bạn đang tìm là System.Reflection.InterfaceMapping.

Type ifaceType = typeof(TempInterface); 
Type tempType = typeof(TempClass); 
InterfaceMapping map = tempType.GetInterfaceMap(ifaceType); 
for (int i = 0; i < map.InterfaceMethods.Length; i++) 
{ 
    MethodInfo ifaceMethod = map.InterfaceMethods[i]; 
    MethodInfo targetMethod = map.TargetMethods[i]; 
    Debug.WriteLine(String.Format("{0} maps to {1}", ifaceMethod, targetMethod)); 
} 
3

xây dựng trên answer by MrKurt:

var targetMethods = 
    from iface in typeof(TempClass).GetInterfaces() 
    from method in typeof(TempClass).GetInterfaceMap(iface).TargetMethods 
    select method; 

var explicitProps = 
    from prop in typeof(TempClass).GetProperties(BindingFlags.Instance | 
               BindingFlags.NonPublic) 
    where targetMethods.Contains(prop.GetGetMethod(true)) || 
      targetMethods.Contains(prop.GetSetMethod(true)) 
    select prop; 
0

này có vẻ hơi đau đớn không có lý do rõ ràng!

Giải pháp của tôi là dành cho trường hợp bạn biết tên của thuộc tính bạn đang tìm kiếm và khá đơn giản.

Tôi có một lớp học để làm phản chiếu dễ dàng hơn một chút mà tôi vừa có thêm trường hợp này để:

public class PropertyInfoWrapper 
{ 
    private readonly object _parent; 
    private readonly PropertyInfo _property; 

    public PropertyInfoWrapper(object parent, string propertyToChange) 
    { 
     var type = parent.GetType(); 
     var privateProperties= type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance); 

     var property = type.GetProperty(propertyToChange) ?? 
         privateProperties.FirstOrDefault(p => UnQualifiedNameFor(p) == propertyName); 

     if (property == null) 
      throw new Exception(string.Format("cant find property |{0}|", propertyToChange)); 

     _parent = parent; 
     _property = property; 
    } 

    private static string UnQualifiedNameFor(PropertyInfo p) 
    { 
     return p.Name.Split('.').Last(); 
    } 

    public object Value 
    { 
     get { return _property.GetValue(_parent, null); } 
     set { _property.SetValue(_parent, value, null); } 
    } 
} 

Bạn không thể chỉ làm == vào tên vì tính thực hiện một cách rõ ràng có tên đầy đủ.

GetProperties cần cả cờ tìm kiếm để nhận được thuộc tính riêng tư.

0

Một lớp helper đơn giản mà có thể giúp:

public class InterfacesPropertiesMap 
{ 
    private readonly Dictionary<Type, PropertyInfo[]> map; 

    public InterfacesPropertiesMap(Type type) 
    { 
     this.Interfaces = type.GetInterfaces(); 
     var properties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 

     this.map = new Dictionary<Type, PropertyInfo[]>(this.Interfaces.Length); 

     foreach (var intr in this.Interfaces) 
     { 
      var interfaceMap = type.GetInterfaceMap(intr); 
      this.map.Add(intr, properties.Where(p => interfaceMap.TargetMethods 
                .Any(t => t == p.GetGetMethod(true) || 
                   t == p.GetSetMethod(true))) 
             .Distinct().ToArray()); 
     } 
    } 

    public Type[] Interfaces { get; private set; } 

    public PropertyInfo[] this[Type interfaceType] 
    { 
     get { return this.map[interfaceType]; } 
    } 
} 

Bạn sẽ nhận được các thuộc tính cho mỗi giao diện, thậm chí thực hiện một cách rõ ràng.

Các vấn đề liên quan