在我的插件代码中,我使用早期绑定实体(通过crmsvcutil生成)。在我的代码中,我使用MemberExpression来检索属性的名称。例如,如果我想要启动插件的用户的全名,请执行以下操作
SystemUser pluginExecutedBy = new SystemUser();
pluginExecutedBy = Common.RetrieveEntity(service
, SystemUser.EntityLogicalName
, new ColumnSet(new string[] {Common.GetPropertyName(() => pluginExecutedBy.FullName)})
, localContext.PluginExecutionContext.InitiatingUserId).ToEntity<SystemUser>();
GetPropertyName的代码如下
public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name.ToLower();
}
RetrieveEntity的代码如下
public static Entity RetrieveEntity(IOrganizationService xrmService, string entityName, ColumnSet columns, Guid entityId)
{
return (Entity)xrmService.Retrieve(entityName, entityId, columns);
}
我的解决方案架构师的评论:
不是像上面那样编写代码,为什么不这样编写它(硬编码字段的名称 - 或使用结构)。
SystemUser pluginExecutedBy = null;
pluginExecutedBy = Common.RetrieveEntity(service
, SystemUser.EntityLogicalName
, new ColumnSet(new string[] {"fullname"})
, localContext.PluginExecutionContext.InitiatingUserId).ToEntity<SystemUser>();
原因:
new
关键字实例化对象以便将其与我的GetProperty方法一起使用时)这是一种糟糕的编程习惯。在我的代码中,我从未使用new
关键字,但只是强制转换它并且转换不会创建新对象。 现在,我不是C#或.NET的专家,但我喜欢阅读并尝试不同的东西。所以,我查找了Microsoft.Xrm.Sdk.dll并发现Sdk中的ToEntity实际上确实使用关键字new
创建了一个新的实体。 问题
我的代码写得不好吗?如果是这样,为什么?如果它更好 - 为什么? (我相信它更清洁,即使字段名称发生变化,只要重新生成早期绑定类文件,我就不必重新编写任何代码)
我同意强制转换不会创建新对象,但我的代码是否会不必要地创建对象?
编写代码有更好的方法(完全不同的第三种方式)吗?
注意:我建议使用GetPropertyName,因为他在整个代码中都是硬编码属性名称,所以在一个不使用早期绑定实体的不同项目中,我使用了属性名称的结构 - 如下所示。我在CRM 2011的新工作中做了3周,但后来发现了MemberExpression的神奇之处。他正在为他在插件中使用的每个实体编写一个大量的cs文件,我告诉他他不必做任何这些,因为他可以在他的插件中使用我的GetPropertyName方法并获得所需的所有字段这促使此代码审查评论。通常他不会进行代码审查。
public class ClientName
{
public struct EntityNameA
{
public const string LogicalName = "new_EntityNameA";
public struct Attributes
{
public const string Name = "new_name";
public const string Status = "new_status";
}
}
}
PS:或者分析不值得的问题/时间是什么?
答案 0 :(得分:3)
Early Bound,Late Bound,MemberExpression,bla bla bla :))
我可以理解“哲学”,但是在我的脑海中看着你的代码是一个巨大的警报:
public static Entity RetrieveEntity(IOrganizationService xrmService, string entityName, ColumnSet columns, Guid entityId)
{
return (Entity)xrmService.Retrieve(entityName, entityId, columns);
}
Retrieve
如果找不到记录则会引发异常。
关于其他事情,GetPropertyName
是好的,但总是选择,例如我尝试使用总是在插件中的后期绑定,也许在项目中我更喜欢使用早期绑定,通常有更多解决问题的一种方法。
快乐的crm编码!
答案 1 :(得分:2)
尽管GetPropertyName
是一个非常聪明的解决方案,我不喜欢它,这完全与可读性有关。对我来说,更容易理解发生了什么:new ColumnSet(new string[] {"fullname"})
。
但这几乎是个人偏好,但重要的是要记住,不仅为自己编写代码,而是为团队编写代码,他们应该能够轻松理解您所做的工作。
作为一方,硬编码字符串可能在运行时表现更好。我通常硬编码我的所有值,如果CRM中的实体模型发生变化,我将不得不重新考虑在任何情况下进行更改。在那种情况下,早期和晚期之间没有区别。
我不明白这个功能的意义,
public static Entity RetrieveEntity(IOrganizationService xrmService, string entityName, ColumnSet columns, Guid entityId)
{
return (Entity)xrmService.Retrieve(entityName, entityId, columns);
}
它没有做任何事情(除了演员已经属于那种类型)。
1.您的代码在需要它之前不必要地创建一个对象(当您使用new关键字实例化对象之前 RetrieveEntity以便与我的GetProperty方法一起使用) 糟糕的编程习惯。在我的代码中,我从未使用过新的代码 关键字,但只是铸造它和铸造不会创建一个新的 对象
我相信这是指; SystemUser pluginExecutedBy = new SystemUser();
我可以在这里看到他/她的观点,在这种情况下new SystemUser()
没有做太多,但如果你实例化的对象做了一些资源密集(加载文件,打开数据库连接),你可能会做一些“浪费”的事情。在这种情况下,如果改变SystemUser pluginExecutedBy = null;
实际上会产生任何显着的性能提升,我会感到惊讶。
2.如果Common.Retrieve返回null,则代码会不必要地分配内存,从而导致性能问题
如果引起性能问题,我会感到惊讶,无论如何,Guido指出函数在任何情况下都不会返回null。
总的来说,这个代码很少,我强烈感觉需要改变 - 但事情可能总是更好,值得讨论(例如代码审查的重点),尽管你可能很难不对你的代码。
我个人会使用硬编码的属性名称并转储Common.RetrieveEntity函数,因为它没有做任何事情。
pluginExecutedBy = service.Retrieve(SystemUser.EntityLogicalName, localContext.PluginExecutionContext.InitiatingUserId, new ColumnSet(new String[] {"fullname"} ));