1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Collections.ObjectModel;
5 using System.Linq.Expressions;
6 using System.Reflection;
7 using System.Text;
8 using System.Linq;
9 using System.Data.Linq.Mapping;
10 using System.Data.Linq.Provider;
11 
12 namespace System.Data.Linq.SqlClient {
13     /// <summary>
14     /// This class defines the rules for inheritance behaviors. The rules:
15     ///
16     ///  (1) The same field may not be mapped to different database columns.
17     ///      The DistinguishedMemberName and AreSameMember methods describe what 'same' means between two MemberInfos.
18     ///  (2) Discriminators held in fixed-length fields in the database don't need
19     ///      to be manually padded in inheritance mapping [InheritanceMapping(Code='x')].
20     ///
21     /// </summary>
22     static class InheritanceRules {
23         /// <summary>
24         /// Creates a name that is the same when the member should be considered 'same'
25         /// for the purposes of the inheritance feature.
26         /// </summary>
DistinguishedMemberName(MemberInfo mi)27         internal static object DistinguishedMemberName(MemberInfo mi) {
28             PropertyInfo pi = mi as PropertyInfo;
29             FieldInfo fi = mi as FieldInfo;
30             if (fi != null) {
31                 // Human readable variant:
32                 // return "fi:" + mi.Name + ":" + mi.DeclaringType;
33                 return new MetaPosition(mi);
34             }
35             else if (pi != null) {
36                 MethodInfo meth = null;
37 
38                 if (pi.CanRead) {
39                     meth = pi.GetGetMethod();
40                 }
41                 if (meth == null && pi.CanWrite) {
42                     meth = pi.GetSetMethod();
43                 }
44                 bool isVirtual = meth != null && meth.IsVirtual;
45 
46                 // Human readable variant:
47                 // return "pi:" + mi.Name + ":" + (isVirtual ? "virtual" : mi.DeclaringType.ToString());
48 
49                 if (isVirtual) {
50                     return mi.Name;
51                 } else {
52                     return new MetaPosition(mi);
53                 }
54             }
55             else {
56                 throw Error.ArgumentOutOfRange("mi");
57             }
58         }
59 
60         /// <summary>
61         /// Compares two MemberInfos for 'same-ness'.
62         /// </summary>
AreSameMember(MemberInfo mi1, MemberInfo mi2)63         internal static bool AreSameMember(MemberInfo mi1, MemberInfo mi2) {
64             return DistinguishedMemberName(mi1).Equals(DistinguishedMemberName(mi2));
65         }
66 
67         /// <summary>
68         /// The representation of a inheritance code when mapped to a specific provider type.
69         /// </summary>
InheritanceCodeForClientCompare(object rawCode, System.Data.Linq.SqlClient.ProviderType providerType)70         internal static object InheritanceCodeForClientCompare(object rawCode, System.Data.Linq.SqlClient.ProviderType providerType) {
71             // If its a fixed-size string type in the store then pad it with spaces so that
72             // comparing the string on the client agrees with the value returnd on the store.
73             if (providerType.IsFixedSize && rawCode.GetType()==typeof(string)) {
74                 string s = (string) rawCode;
75                 if (providerType.Size.HasValue && s.Length!=providerType.Size) {
76                     s = s.PadRight(providerType.Size.Value).Substring(0,providerType.Size.Value);
77                 }
78                 return s;
79             }
80             return rawCode;
81         }
82 
83 
84     }
85 }
86