Ok, zaproponuję nową odpowiedź (trochę za późno, przepraszam), która zadziała, nawet jeśli zmieni się nazwa stowarzyszenia.
Ta metoda wyszuka właściwości powiązania głównej encji, a następnie wyszuka wartość w tabeli głównej. Wyobraź sobie:
Tabela: Orders
, do której odwołuje się tabela Customers
przez Orders.CustomerID
jest równa Customers.Id
. Tak więc przekazujemy informacje Meta głównego stołu, pole CustomerID
(które jest polem odniesienia) i pole Name
(które jest wartością, którą chcemy).
/// <summary>
/// Gets the value of "referencedValueFieldName" of an associated table of the "fieldName" in the "mainTable".
/// This is equivalent of doing the next LINQ query:
/// var qryForeignValue =
/// from mt in modelContext.mainTable
/// join at in modelContext.associatedTable
/// on mt.fieldName equals at.associatedField
/// select new { Value = at.referencedValueField }
/// </summary>
/// <param name="mainTable">Metadata of the table of the fieldName's field</param>
/// <param name="fieldName">Name of the field of the foreign key</param>
/// <param name="referencedValueFieldName">Which field of the foreign table do you the value want</param>
/// <returns>The value of the referenced table</returns>
/// <remarks>This method only works with foreign keys of one field.</remarks>
private Object GetForeignValue(MetaTable mainTable, string fieldName, string referencedValueFieldName) {
Object resultValue = null;
foreach (MetaDataMember member in mainTable.RowType.DataMembers) {
if ((member.IsAssociation) && (member.Association.IsForeignKey)) {
if (member.Association.ThisKey[0].Name == fieldName) {
Type associationType = fPointOfSaleData.GetType();
PropertyInfo associationInfo = associationType.GetProperty(member.Name);
if (associationInfo == null)
throw new Exception("Association property not found on member");
Object associationValue = associationType.InvokeMember(associationInfo.Name, BindingFlags.GetProperty, null, fPointOfSaleData, null);
if (associationValue != null) {
Type foreignType = associationValue.GetType();
PropertyInfo foreignInfo = foreignType.GetProperty(referencedValueFieldName);
if (foreignInfo == null)
throw new Exception("Foreign property not found on assiciation member");
resultValue = foreignType.InvokeMember(foreignInfo.Name, BindingFlags.GetProperty, null, associationValue, null);
}
break;
}
}
}
return resultValue;
}
i wezwanie:
AttributeMappingSource mapping = new System.Data.Linq.Mapping.AttributeMappingSource();
MetaModel model = mapping.GetModel(typeof(WhateverClassesDataContext));
MetaTable table = model.GetTable(typeof(Order));
Object value = GetForeignValue(table, "CustomerId" /* In the main table */, "Name" /* In the master table */);
Problemem jest to, że działa tylko z kluczy obcych z tylko jednej dziedzinie odwołania. Ale zmiana na wiele kluczy jest dość banalna.
Jest to metoda uzyskania wartości pola tabeli wzorcowej, którą można zmienić, aby zwrócić cały obiekt.
PS: Myślę, że popełniam błędy w związku z moim angielskim, jest to dla mnie dość trudne.
Można to faktycznie zrobić krok dalej i użycie _OriginalPoorlyNamedStorageVariable można całkowicie pominąć. Nie jestem jednak pewien, czy dodanie własnej zmiennej pamięci w konstruktorze nie spowoduje innych komplikacji, ale prawdopodobnie wkrótce się dowiem ... – jahu