Получение ранних связей
Когда я связываю аннотации с конкретным сущностью, а не создаю такие отношения:
var associateRequest = new AssociateRequest
{
Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
RelatedEntities = new EntityReferenceCollection
{
new EntityReference(Annotation.EntityLogicalName, noteGuid),
},
Relationship = new Relationship("SalesOrder_Annotation")
};
Можно ли связать отношения строго типизированным способом:
var associateRequest = new AssociateRequest
{
Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
RelatedEntities = new EntityReferenceCollection
{
new EntityReference(Annotation.EntityLogicalName, noteGuid)
},
Relationship = SalesOrder.Relationships.SalesOrder_Annotation // <----- ???
};
Это было бы похоже на возможность получить логическое имя во время разработки:
SalesOrder.EntityLogicalName
Можно ли ссылаться на конкретные отношения 1: N таким же образом:
SalesOrder.Relationships.SalesOrder_Annotation
Ответы
Ответ 1
Значение, которое вы ищете, хранится в атрибуте кода RelationshipSchemaNameAttribute
, если вы создаете свой код с помощью стандартного приложения CrmSvcUtil.exe
, предоставленного в SDK (\SDK\Bin\CrmSvcUtil.exe
). Я проверил этот код в консольном приложении, используя файл класса ранней связанной сущности, предоставленный в SDK (\SDK\SampleCode\CS\HelperCode\MyOrganizationCrmSdkTypes.cs
).
Вызвать метод следующим образом (в вашем примере):
var relationship = GetRelationship<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))
Или, если вы хотите вернуть фактическое строковое значение:
var relationshipName = GetRelationshipSchemaName<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))
Добавьте этот код в класс-помощник в вашем приложении:
public static string GetRelationshipSchemaName<T>(string relationshipPropertyName) where T:Entity
{
return typeof (T).GetProperties()
.FirstOrDefault(x => x.Name == relationshipPropertyName)
.GetCustomAttributes()
.OfType<RelationshipSchemaNameAttribute>()
.FirstOrDefault()
?.SchemaName;
}
public static Relationship GetRelationship<T>(string relationshipPropertyName) where T : Entity
{
return new Relationship(typeof(T).GetProperties()
.FirstOrDefault(x => x.Name == relationshipPropertyName)
.GetCustomAttributes()
.OfType<RelationshipSchemaNameAttribute>()
.FirstOrDefault()
?.SchemaName);
}
Это будет выглядеть ваш обновленный код:
var associateRequest = new AssociateRequest
{
Target =
new EntityReference(
SalesOrder.EntityLogicalName,
salesOrderGuid),
RelatedEntities =
new EntityReferenceCollection
{
new EntityReference(
Annotation
.EntityLogicalName,
noteGuid)
},
Relationship = GetRelationship<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation)) ///////////????
};
Ответ 2
С другой стороны, мой ответ на шаблон t4 кажется излишним
Вы можете использовать деревья выражений и метод расширения, чтобы легко получить то, что вам нужно
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication9
{
internal class Program
{
private static void Main(string[] args)
{
Relationship r = new Class1().GetRelationShip(s => s.RelationShipProperty);
Console.WriteLine(r.Name);
System.Console.ReadLine();
}
}
public static class MyExtention
{
public static Relationship GetRelationShip<T, TProperty>(this T t, Expression<Func<T, TProperty>> expression)
{
return new Relationship(((expression.Body as MemberExpression).Member as PropertyInfo)
.GetCustomAttributes(typeof(RelationshipAttribute))
.Select(a=>(RelationshipAttribute)a)
.First().Name
);
}
}
public class RelationshipAttribute : System.Attribute
{
public string Name { get; set; }
public RelationshipAttribute(string name)
{
Name = name;
}
}
public class Relationship
{
public string Name { get; set; }
public Relationship(string name)
{
Name = name;
}
}
public class Class1
{
[Relationship("RelationShipA")]
public List<int> RelationShipProperty { get; set; }
}
}
Ответ 3
Из того, что вы сказали, ваши сгенерированные классы имеют атрибут с именем ваших отношений.
Все, что вам нужно, это шаблон t4, который генерирует класс с сильно типизированными свойствами для ваших отношений
Скажем, у вас есть следующий код в вашем проекте
namespace ConsoleApplication9
{
public class RelationshipAttribute : System.Attribute
{
public string Name { get; set; }
public RelationshipAttribute(string name) { Name = name; }
}
[Relationship("RelationShipA")]
public class Class1 { }
[Relationship("RelationShipB")]
public class Class2 { }
[Relationship("RelationShipC")]
public class Class3 { }
}
Этот шаблон
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="$(TargetPath)" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ output extension=".cs" #>
namespace YourNameSpace
{
public static class Relationships
{
<#
var types = typeof(ConsoleApplication9.RelationshipAttribute).Assembly
.GetTypes()
.Select(t => new { t.Name, Value = t.GetCustomAttribute(typeof(ConsoleApplication9.RelationshipAttribute)) })
.Where(t => t.Value != null)
.Select(t=> new { t.Name,Value= ((ConsoleApplication9.RelationshipAttribute)t.Value).Name })
.ToList();
foreach (var attr in types)
{ #>
public static class <#= attr.Name #>
{
public const string <#= attr.Value #> = "<#= attr.Value #>";
}
<# }
#>}
}
создаст следующий файл .cs
namespace YourNameSpace
{
public static class Relationships
{
public static class Class1
{
public const string RelationShipA = "RelationShipA";
}
public static class Class2
{
public const string RelationShipB = "RelationShipB";
}
public static class Class3
{
public const string RelationShipC = "RelationShipC";
}
}
}
Затем вы можете использовать его как
Relationship = new Relationship(Relationships.Class1.RelationShipA )
Ответ 4
Я не уверен, правильно ли получил вопрос.
Не будет ли функция С# 6.0 nameof(...)
делать?
т.
new Relationship(nameof(RelationshipSalesOrder.Relationships.SalesOrder_Annotation));