![](/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.