2017-02-24 47 views
0

如何避免重複代碼?如何在運行時綁定到特定的IQueryable

我有一個控制器 - >服務架構,其中控制器將調用服務中的方法。例如下面我們有一個AccountController,將調用GetCrmAccountAccountService

public class AccountController : ApiController 
    { 
     private readonly IAccountService _AccountService; 

     [Route("Account({AccountGuid:guid})", Name = "GetAccountByGuid")] 
     [HttpGet] 
     [CacheOutput(ServerTimeSpan = 300)] 
     public Account GetAccountByGuid(Guid AccountGuid) 
     { 
      var Account = _AccountService.GetCrmAccount(AccountGuid); 
      return Account; 
     } 
} 

我的服務:

public class AccountService : IAccountService 
{ 
    private readonly XrmServiceContext _xrmServiceContext; 

    public AccountService(XrmServiceContext xrmServiceContext) 
    { 
     _xrmServiceContext = xrmServiceContext; 
    } 
    public chr_servicelocation GetCrmLocation(Guid locationGuid) 
    { 
     return _xrmServiceContext.chr_servicelocationSet.FirstOrDefault(x => x.Id == locationGuid); 
    } 

我的問題是,我有其他控制器非常類似的要求。例如,我可以有一個名爲AccountLeadsController控制器,將有它自己的服務AccountLeadsService,這將有同樣的方法GetCrmAccountLead,這也將返回:

_xrmServiceContext.AccountLeadSet.FirstOrDefault(x => x.Id == accountLeadGuid); 

而不是必須爲每個服務創建此方法在我的解決方案中,有沒有一種方法可以抽象出這種行爲?

下面是有IQueryables類的定義:

/// <summary> Gets CRM Account by Guid. </summary> 
    /// <param name="AccountGuid"> Guid of the Account to fetch. </param> 
    /// <returns> The CRM Account. </returns> 
    public chr_serviceAccount GetCrmAccount(Guid AccountGuid) 
    { 
     return _xrmServiceContext.AccountSet.FirstOrDefault(x => x.Id == AccountGuid); 
    } 

/// <summary> 
    /// Represents a source of entities bound to a CRM service. It tracks and manages changes made to the retrieved entities. 
    /// </summary> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("CrmSvcUtil", "5.0.9690.3339")] 
    public partial class XrmServiceContext : Microsoft.Xrm.Sdk.Client.OrganizationServiceContext 
    { 

     /// <summary> 
     /// Constructor. 
     /// </summary> 
     public XrmServiceContext(Microsoft.Xrm.Sdk.IOrganizationService service) : 
       base(service) 
     { 
     } 

     /// <summary> 
     /// Gets a binding to the set of all <see cref="Xrm.Account"/> entities. 
     /// </summary> 
     public System.Linq.IQueryable<Xrm.Account> AccountSet 
     { 
      get 
      { 
       return this.CreateQuery<Xrm.Account>(); 
      } 
     } 

     /// <summary> 
     /// Gets a binding to the set of all <see cref="Xrm.AccountLeads"/> entities. 
     /// </summary> 
     public System.Linq.IQueryable<Xrm.AccountLeads> AccountLeadsSet 
     { 
      get 
      { 
       return this.CreateQuery<Xrm.AccountLeads>(); 
      } 
     } 

     /// <summary> 
     /// Gets a binding to the set of all <see cref="Xrm.ActivityMimeAttachment"/> entities. 
     /// </summary> 
     public System.Linq.IQueryable<Xrm.ActivityMimeAttachment> ActivityMimeAttachmentSet 
     { 
      get 
      { 
       return this.CreateQuery<Xrm.ActivityMimeAttachment>(); 
      } 
     } 

     /// <summary> 
     /// Gets a binding to the set of all <see cref="Xrm.ActivityParty"/> entities. 
     /// </summary> 
     public System.Linq.IQueryable<Xrm.ActivityParty> ActivityPartySet 
     { 
      get 
      { 
       return this.CreateQuery<Xrm.ActivityParty>(); 
      } 
     } 
... 
} 
+0

我不知道我跟着你想要什麼,但如果它是對一組相關的服務,可以是同樣的方法通過將方法添加到基類來完成所有繼承的服務,或者通過確保所有服務具有相同的接口並添加擴展方法來滿足需要。你將不得不決定哪一個最適合你的情況。 –

+0

@DavidCulp我認爲也許反射可能是唯一的出路.... XrmServiceContext是動態生成的,所以我不能強迫它遵循一個接口 –

回答

1

也許擴展方法+泛型是要走的路?

public static XrmServiceContextExtensions 
{ 

    public static T GetEntityRecordById<T>(this XrmServiceContext ctx, Guid Id) where T: Entity { 
     return ctx.CreateQuery<T>().Where(e => e.Id == Id).FirstOrDefault(); 
    } 

} 

但納悶,爲什麼不直接使用XrmServiceContext:

的線沿線的東西嗎?

舉例來說,我做的很簡單,就是在我的Web應用程序中,我只是在控制器級別保留對IOrganizationService的引用,然後可以使用它來創建XrmServiceContext實例,以及我可以使用使用FakeXrmEasy從單元測試項目注入虛假服務的相同IOrganizationService引用。

0

我想看看DLaB.Xrm(Nuget包)中的擴展方法。它提供了對IOrganizationService一個通用的擴展方法,所以它只是

service.GetEntity<Account>(id); 
相關問題