2017-02-21 49 views
14

當我鏈接註釋到特定的實體,而不是創造像這樣的關係:獲得一個早期綁定關係

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 // <----- ??? 
}; 

這將是類似能夠得到logicalname在開發時間:

SalesOrder.EntityLogicalName 

我們可以參考具體的1:N的關係一樣:

SalesOrder.Relationships.SalesOrder_Annotation 
+0

'SalesOrder.Relationships.SalesOrder_Annotation'返回的類型是什麼?如果它不是「關係」,那麼不是,你不能稱它。我不得不問,因爲'SalesOrder.Relationships.SalesOrder_Annotation'不可用使用標準的CrmSvcUtil.exe代碼gen工具 - 所以它非常自定義。 – Nicknow

+0

是否使用可使用entity.relationship名稱或類似方法調用的crmsvcutil可用的任何關係? –

+0

不是。你將不得不創建一個擴展來生成具有關係名稱的'const'或'readonly'字符串。或者寫一個方法從'CrmSvcUtil.exe'輸出的代碼屬性中讀取關係名稱。 – Nicknow

回答

4

從你說的話,你生成的類必須與你的關係的名稱的屬性。
所有你需要的是,對你的人際關係產生具有強類型屬性的類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) 
+1

@Downvoter不知道這個答案值得downvote ...它可能比其他人更復雜,但另一方面它沒有性能損失......如果OP想要使用代碼它循環它可能是最好的答案 –

6

您正在尋找存儲在一個代碼屬性,RelationshipSchemaNameAttribute,如果你使用的SDK(\SDK\Bin\CrmSvcUtil.exe)提供的標準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)) ///////////???? 
            }; 
5

關於第二個想法,我的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; } 
    } 
} 
4

我不確定我是否正確回答問題。 不會C#6.0功能nameof(...)做的事情?

即。

new Relationship(nameof(RelationshipSalesOrder.Relationships.SalesOrder_Annotation)); 
+0

問題(據我所知)是「RelationshipSalesOrder.Relationships.SalesOrder_Annotation」不存在。如果存在,是的,你可以這樣做 –

+0

@GeorgeVovos是正確的。沒有'RelationshipSalesOrder.Relationships.SalesOrder_Annotation',即使它存在,也不一定匹配'Relationship'構造函數需要的字符串值。 – Nicknow