C# Dynamics 365-使用IOrganizationService创建OrganizationServiceProxy

C# Dynamics 365-使用IOrganizationService创建OrganizationServiceProxy,c#,dynamics-crm,dynamics-crm-online,C#,Dynamics Crm,Dynamics Crm Online,我有一个定制实体的处理程序类(这里处理一些sdk请求),这个处理程序在许多插件/类中都被引用。必须通过管理上下文而不是调用用户访问此实体。我们不是将“通过管理guid创建的”服务传递给处理程序类,而是尝试在处理程序类内模拟该服务。比如, -----插件内部----- 在我的实体处理程序中,首先将IOOrganizationService实例的CallerID强制转换为OrganizationServiceProxy,从而更改该实例的CallerID -----在处理器内部----- 我在强制转

我有一个定制实体的处理程序类(这里处理一些sdk请求),这个处理程序在许多插件/类中都被引用。必须通过管理上下文而不是调用用户访问此实体。我们不是将“通过管理guid创建的”服务传递给处理程序类,而是尝试在处理程序类内模拟该服务。比如,

-----插件内部-----

在我的实体处理程序中,首先将IOOrganizationService实例的CallerID强制转换为OrganizationServiceProxy,从而更改该实例的CallerID

-----在处理器内部-----


我在强制转换部分中获得“Exception:System.NullReferenceException:Object reference未设置为对象的实例”。
有没有办法做这样的事。我希望我解释得足够清楚,谢谢…

您可以传递
null
,以便在
CreateOrganizationService
期间系统用户可以由工厂模拟

// Use the factory to generate the Organization     
Service.OrganizationServiceImpersonated = factory.CreateOrganizationService(null);

这不起作用,因为传递给插件的对象不是
OrganizationServiceProxy
,它在某些外部应用程序中使用,但在插件中不使用。插件中的对象根据隔离模式不同,据我所知,对于非隔离模式,它是
Microsoft.Xrm.Extensibility.InprocessProxyService
,对于沙盒模式,它是
Microsoft.Crm.Sandbox.SandboxOrganizationServiceWrapper
。这两种类型都不在SDK中,因此您只能通过反射访问它们的属性。第一个具有CallerId属性,因此您应该能够使用反射来访问它,但第二个没有,因此我认为不可能替换此呼叫者id

您应该采取的唯一有效方法是将
ioorganizationservicefactory
传递给处理程序,而不是
ioorganizationservice
,然后根据需要创建
ioorganizationservice
。如果你不想改变你的整个项目结构(我相信这是最好的方法,但我已经知道人们害怕重构,没有什么好的理由,我们最终会陷入笨拙的项目,在经过几年的维护后不得不重写)只需为处理程序创建第二个构造函数,该构造函数将把
ioOrganizationServiceFactory
作为参数-这将保持现有代码的完整性,在需要同时使用管理服务和非管理服务的处理程序中,只需使用第二个构造函数即可

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…)

首先感谢您的回复,如果我错了,请原谅。据我所知,您的建议是使用serviceProvider或factory创建模拟服务,但实际上,我正在寻找我可以在处理程序中执行的操作,以避免更改所有项目结构。可以尝试类似((OrganizationServiceProxy)的操作this.service).CallerId=新Guid(“AdminGUID”);没有,试过了,但不起作用。隔离模式是否会限制此操作?因为我使用的是dynamics 365,所以沙盒模式是打开的。
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;
    }
}