![](/img/trans.png)
[英]Why use IOrganizationService instead of CrmServiceClient in Dynamics 365 XRM tooling SDK?
[英]Dynamics 365 - Create OrganizationServiceProxy using IOrganizationService
我有一個用於自定義實體的處理程序類(此處處理了一些sdk請求),並且在許多插件/類中都引用了該處理程序。 必須通過管理上下文訪問此實體,而不是調用用戶。 與其將“通過admin guid創建的”服務傳遞給處理程序類,我們不打算在處理程序類中模擬該服務。 例如;
-----插件內部-----
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
// Instead of doing something like this;
var adminOrganizationService = factory.CreateOrganizationService(Guid.Parse("~ADMINGUID~"));
MyEntityHandler myEntityHandler = new MyEntityHandler(adminOrganizationService);
// Use myEntityHandler
// What i want to do is, calling my entity handler with the service of calling user;
MyEntityHandler myEntityHandler = new MyEntityHandler(factory.CreateOrganizationService(context.UserId));
// Use myEntityHandler
然后在我的實體處理程序中,通過將IOrganizationService實例的CallerID強制轉換為OrganizationServiceProxy來進行更改。
-----處理程序內部-----
private IOrganizationService service;
public MyEntityHandler(IOrganizationService organizationService)
{
// This is what i have tried.
service = organizationService;
(service as OrganizationServiceProxy).CallerId = Guid.Parse("~ADMINGUID~");
}
我收到“異常:System.NullReferenceException:對象引用未設置為對象的實例。” 在鑄件中。 有什么辦法可以做這樣的事情。 我希望我能很好地解釋自己,謝謝。
這不僅僅因為傳遞給插件的對象不是在某些外部應用程序中使用但不在插件中使用的OrganizationServiceProxy
所致。 插件中的對象根據隔離模式而有所不同,據我所記得,對於非隔離模式,它是Microsoft.Xrm.Extensibility.InprocessProxyService
;對於沙盒模式,它是Microsoft.Crm.Sandbox.SandboxOrganizationServiceWrapper
。 這兩種類型都不在SDK中,因此您只能通過反射訪問它們的屬性。 第一個具有CallerId屬性,因此您應該可以使用反射來訪問它,但是第二個則不能,因此我認為不可能替換此呼叫者ID。
您應該采取的唯一有效方法是將IOrganizationServiceFactory
而不是IOrganizationService
傳遞給處理程序,然后根據需要創建IOrganizationService
。 如果您不想更改整個項目的結構(我認為這是最好的方法,但是我已經知道人們會出於無理由而害怕重構,而我們最終會遇到笨拙的項目,這些項目之后必須重新編寫)幾年的維護)只需為您的處理程序創建第二個構造函數,該構造函數將IOrganizationServiceFactory
作為參數-這將使您現有的代碼保持完整,並且在需要同時使用admin和IOrganizationServiceFactory
-admin服務的處理程序中,您只需使用第二個構造函數。
public class MyHandler
{
private IOrganizationService service;
private IOrganizationService adminService;
public MyHandler(IOrganizationService service)
{
this.service = service;
}
public MyHandler(IOrganizationServiceFactory factory, Guid userId) //instead of passing userId here, it would be better to pass it to the method that you want to perform
{
this.service = factory.CreateOrganizationService(userId);
this.adminService = factory.CreateOrganizationService(null);
}
}
或簡單地這樣:
public class MyHandler
{
private IOrganizationService service;
private IOrganizationService adminService;
public MyHandler(IOrganizationService service)
{
this.service = service;
}
public MyHandler(IOrganizationService service, IOrganizationService adminService) : this(service)
{
this.adminService = adminService;
}
}
這只是示例,當然我對您的體系結構了解不多,但是可以肯定的是,這種方法將來會比您現在正在嘗試的方法更好,更清潔,更容易維護(沒有充分的理由,再次-不要害怕重構代碼,大多數工作都會為您做Visual Studio ...)
您可以傳遞null
以便在CreateOrganizationService
期間工廠可以模擬系統用戶。
// Use the factory to generate the Organization
Service.OrganizationServiceImpersonated = factory.CreateOrganizationService(null);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.