Чтение всех атрибутов объекта в C#
Предположим, что Вам необходимо вернуть и вывести значения полей определенного объекта. Для единичного случая, конечно можно посмотреть типы полей и их количество и подогнать под них код. Но если решение универсальное и количество и типы поле не известны (или они часто меняются), то и код должен быть универсальным. Например, такой:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using Microsoft.Xrm.Sdk.Messages; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Metadata; using System.ServiceModel; using System.ServiceModel.Description; using System.Runtime.Serialization; namespace RetrieveAttributes { class Program { static void Main(string[] args) { // Подключаемся к CRM ClientCredentials credentials = new ClientCredentials(); credentials.Windows.ClientCredential = new System.Net.NetworkCredential("Administrator", "1qaz@WSX", "D2011"); Uri uri = new Uri("http://crm2011:5555/superfirma/XRMServices/2011/Organization.svc"); OrganizationServiceProxy proxy = new OrganizationServiceProxy(uri, null, credentials, null); proxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior()); IOrganizationService service = (IOrganizationService)proxy; // Возвращаем все поля записи Организация Entity retrievedAccount = service.Retrieve("account", new Guid("14E25FE5-73E2-E111-B2D5-000C29CDB72E"), new ColumnSet(allColumns: true)); // Просматриваем по очереди все возвращенные поля foreach (KeyValuePair<string, object> metaAttribute in retrievedAccount.Attributes) { // Берем один атрибу... object myProp = retrievedAccount.Attributes[metaAttribute.Key]; // ... и запрашиваем его метаданные RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest(); attribReq.EntityLogicalName = retrievedAccount.LogicalName; attribReq.LogicalName = metaAttribute.Key; attribReq.RetrieveAsIfPublished = true; RetrieveAttributeResponse amRes = (RetrieveAttributeResponse)service.Execute(attribReq); AttributeMetadata attmetadata = amRes.AttributeMetadata; // Вызываем метод GetMetadataValue, чтобы он в зависимости от типа атрибута вернул его значение string sMyValue = GetMetadataValue(myProp , amRes); // Выводим название атрибута и его значение Console.WriteLine("{0} \t= {1}", metaAttribute.Key, sMyValue); } Console.WriteLine("\nPress <Enter> to exit."); Console.ReadLine(); } // Метод возвращает значение атрибута в зависимоти от его типа static string GetMetadataValue(object oAttribute, RetrieveAttributeResponse attMetadata) { string sReturn = string.Empty; // Наборы параметров... if (oAttribute.GetType().Equals(typeof(Microsoft.Xrm.Sdk.OptionSetValue))) { OptionMetadata[] optionList = null; // трушный Пиклист if (attMetadata.AttributeMetadata.GetType().FullName.Contains("PicklistAttributeMetadata")) { PicklistAttributeMetadata retrievedPicklistAttributeMetadata = (PicklistAttributeMetadata)attMetadata.AttributeMetadata; optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray(); } // Поле Статуса else if (attMetadata.AttributeMetadata.GetType().FullName.Contains("StatusAttributeMetadata")) { StatusAttributeMetadata retrievedPicklistAttributeMetadata = (StatusAttributeMetadata)attMetadata.AttributeMetadata; optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray(); } // Поле Состояния else if (attMetadata.AttributeMetadata.GetType().FullName.Contains("StateAttributeMetadata")) { StateAttributeMetadata retrievedPicklistAttributeMetadata = (StateAttributeMetadata)attMetadata.AttributeMetadata; optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray(); } else return string.Empty; // Получаем текстовое значение Набора параметров int i = int.Parse((oAttribute as Microsoft.Xrm.Sdk.OptionSetValue).Value.ToString()); for (int c = 0; c < optionList.Length; c++) { OptionMetadata opmetadata = (OptionMetadata)optionList.GetValue(c); if (opmetadata.Value == i) { sReturn = opmetadata.Label.UserLocalizedLabel.Label; break; } } } // Деньги else if (oAttribute.GetType().Equals(typeof(Microsoft.Xrm.Sdk.Money))) { sReturn = (oAttribute as Microsoft.Xrm.Sdk.Money).Value.ToString(); } // Лукап else if (oAttribute.GetType().Equals(typeof(Microsoft.Xrm.Sdk.EntityReference))) { sReturn = (oAttribute as Microsoft.Xrm.Sdk.EntityReference).Name; } // Все остальное - легко преобразуемое в текст else { sReturn = oAttribute.ToString(); } if (sReturn == null || sReturn.Length == 0) sReturn = "No Value"; return sReturn; } } }
Что мы тут делаем:
- Подключаемся к CRM;
- Возвращаем все поля одной записи Организации;
- Просматриваем все возвращенные атрибуты и для каждого из них запрашиваем метаданные;
- Затем сам атрибут и его метаданные передаем в функцию GetMetadataValue, которая на основе типа атрибута, определяет способ извлечения данных атрибута и возвращает их.
А почему не использовать early bound классы?
Лень 🙂 Этож нужно открвыать sdk, зпускать тулзу и т.д. 🙂
А не проще просто просмотреть и вывести коллекцию форматированных атрибутов сущности.
Не совсем понял что Вы имели ввиду?
Андрей наверно имел ввиду что для получения значения в OptionSet достаточно будет использовать соответсвующее значение из FormattedValues колекции в Entity. Тогда метадату можно будет вообще не вычитывать.
Может кто-нибудь подсказать как передать данные из приложения написанного на C# в CRM. Чтобы при передаче создавался объект и в поля записывались данные, которые я передаю.
Ну, тут в двух словах не рассказать 🙂
Как пример можете посмотреть тут: http://mmcrm.ru/?p=2423 и http://mmcrm.ru/?p=2415