1 using System.Collections.Generic;
2 
3 namespace System.ComponentModel.DataAnnotations {
4     /// <summary>
5     /// Used to mark an Entity member as an association
6     /// </summary>
7     [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
8     public sealed class AssociationAttribute : Attribute {
9         private string name;
10         private string thisKey;
11         private string otherKey;
12         private bool isForeignKey;
13 
14         /// <summary>
15         /// Full form of constructor
16         /// </summary>
17         /// <param name="name">The name of the association. For bi-directional associations, the name must
18         /// be the same on both sides of the association</param>
19         /// <param name="thisKey">Comma separated list of the property names of the key values
20         /// on this side of the association</param>
21         /// <param name="otherKey">Comma separated list of the property names of the key values
22         /// on the other side of the association</param>
AssociationAttribute(string name, string thisKey, string otherKey)23         public AssociationAttribute(string name, string thisKey, string otherKey) {
24             this.name = name;
25             this.thisKey = thisKey;
26             this.otherKey = otherKey;
27         }
28 
29         /// <summary>
30         /// Gets the name of the association. For bi-directional associations, the name must
31         /// be the same on both sides of the association
32         /// </summary>
33         public string Name {
34             get { return this.name; }
35         }
36 
37         /// <summary>
38         /// Gets a comma separated list of the property names of the key values
39         /// on this side of the association
40         /// </summary>
41         public string ThisKey {
42             get {
43                 return this.thisKey;
44             }
45         }
46 
47         /// <summary>
48         /// Gets a comma separated list of the property names of the key values
49         /// on the other side of the association
50         /// </summary>
51         public string OtherKey {
52             get {
53                 return this.otherKey;
54             }
55         }
56 
57         /// <summary>
58         /// Gets or sets a value indicating whether this association member represents the foreign key
59         /// side of an association
60         /// </summary>
61         public bool IsForeignKey {
62             get {
63                 return this.isForeignKey;
64             }
65             set {
66                 this.isForeignKey = value;
67             }
68         }
69 
70         /// <summary>
71         /// Gets the collection of individual key members specified in the ThisKey string.
72         /// </summary>
73         public IEnumerable<string> ThisKeyMembers {
74             get {
75                 return GetKeyMembers(this.ThisKey);
76             }
77         }
78 
79         /// <summary>
80         /// Gets the collection of individual key members specified in the OtherKey string.
81         /// </summary>
82         public IEnumerable<string> OtherKeyMembers {
83             get {
84                 return GetKeyMembers(this.OtherKey);
85             }
86         }
87 
88         /// <summary>
89         /// Parses the comma delimited key specified
90         /// </summary>
91         /// <param name="key">The key to parse</param>
92         /// <returns>Array of individual key members</returns>
GetKeyMembers(string key)93         private static string[] GetKeyMembers(string key) {
94             return key.Replace(" ", string.Empty).Split(',');
95         }
96     }
97 }
98