我有一个自定义实体的处理程序类(这里处理了一些sdk请求),并且在许多插件/类中引用了这个处理程序。必须通过管理上下文访问此实体,而不是调用用户。我们试图模拟处理程序类中的服务,而不是将“通过管理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
在我的实体处理程序中,首先通过将其转换为OrganizationServiceProxy来更改IOrganizationService实例的CallerID。
-----处理程序内部-----
private IOrganizationService service;
public MyEntityHandler(IOrganizationService organizationService)
{
// This is what i have tried.
service = organizationService;
(service as OrganizationServiceProxy).CallerId = Guid.Parse("~ADMINGUID~");
}
我得到'异常:System.NullReferenceException:对象引用未设置为对象的实例。'在铸造部分。 有没有办法做这样的事情。我希望我能够很好地解释自己,谢谢...
答案 0 :(得分:1)
这不起作用,因为传递给插件的对象不是OrganizationServiceProxy
,而是在某些外部应用程序中使用但不在插件中。插件中的对象因隔离模式而异,据我记得非隔离模式为Microsoft.Xrm.Extensibility.InprocessProxyService
,而沙箱模式为Microsoft.Crm.Sandbox.SandboxOrganizationServiceWrapper
。这两种类型都不在SDK中,因此您只能使用反射访问其属性。第一个具有CallerId属性,因此您应该能够使用反射访问它,但第二个没有,所以我不认为可以替换此调用者ID。
您应采取的唯一有效方法是将IOrganizationServiceFactory
传递给处理程序而不是IOrganizationService
,然后根据您的需要创建IOrganizationService
。如果你不想改变你的整个项目结构(我认为这是最好的方法,但我已经知道人们害怕重构,没有充分的理由,我们最终会陷入笨拙的项目,必须经过几年的维护后重写)只需为你的处理程序创建第二个构造函数,它将IOrganizationServiceFactory
作为参数 - 这将保持现有代码的完整性和处理程序,你需要同时使用admin和not-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 ......)
答案 1 :(得分:0)
您可以传递null
,以便CreateOrganizationService
期间工厂可以模拟系统用户。
// Use the factory to generate the Organization
Service.OrganizationServiceImpersonated = factory.CreateOrganizationService(null);