c# - setIfNull 扩展方法不会将值设置给对象

标签 c# entity-framework generics reflection extension-methods

我想创建一个通用扩展方法,如果对象或结构的值等于其默认值,该方法将为其设置一个值。

所以我有以下代码:

public static void setIfNull<T>(this T i_ObjectToUpdate, T i_DefaultValue)
{
    if (EqualityComparer<T>.Default.Equals(i_ObjectToUpdate, default(T)))
    {
        i_ObjectToUpdate = i_DefaultValue;
    }
}

这是一个调用示例:

public OrganizationalUnit CreateOrganizationalUnit(OrganizationalUnit i_UnitToCreate)
{
    i_UnitToCreate.EntityCreationDate.setIfNull(DateTime.Now); //Here is a call
    i_UnitToCreate.EntityLastUpdateDate.setIfNull(DateTime.Now); //And another one
    m_Context.DomainEntities.Add(i_UnitToCreate);
    return i_UnitToCreate;
}

我不知道这是否与此有关,但我使用 Entity Framework 和 MVC。

调试器中实际发生的情况我看到扩展方法中的行 i_ObjectToUpdate = i_DefaultValue; 正在工作并且值发生了变化,但是当调试器退出扩展方法时,我看到i_UnitToCreate.EntityCreationDate 的值保持不变。

知道哪里出了问题吗?

最佳答案

您的代码中有两个引用。其中之一是i_UnitToCreate.EntityCreationDate,它指向内存中的某个地址。另一个是扩展方法中的 i_ObjectToUpdate,它最初也指向该地址(您在传递 i_UnitToCreate.EntityCreationDate 引用时创建地址副本按照你的方法)。稍后您将第二个引用更改为指向内存中其他对象,但这不会更改第一个引用,因为它们是独立的。

解决方法

public static void SetIfDefault<T, TProperty>(this T arg,
    Expression<Func<T, TProperty>> propertySelector, TProperty value)
{
    TProperty currentValue = propertySelector.Compile()(arg);
    EqualityComparer<TProperty> comparer = EqualityComparer<TProperty>.Default;
    if (!comparer.Equals(currentValue, default(TProperty)))
        return;
    PropertyInfo property = (PropertyInfo)((MemberExpression)propertySelector.Body).Member;
    property.SetValue(arg, value);
} 

您可以使用表达式将属性选择器(而不是属性值)传递给扩展方法。从编译表达式中检索值。如果它是默认值,则通过反射(您可以通过转换成员表达式轻松获取PropertyInfo)设置新值。用法:

i_UnitToCreate.SetIfDefault(x => x.EntityCreationDate, DateTime.Now);
i_UnitToCreate.SetIfDefault(x => x.EntityLastUpdateDate, DateTime.Now);

PS 关于我的第一个答案,有一个评论 - 当谈到复制引用值时,我认为通用 T 类型是引用类型。对于值类型(如 DateTime),整个对象都会被复制。它不会改变结果(您不能分配新值),但需要提及。

关于c# - setIfNull 扩展方法不会将值设置给对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13540024/

相关文章:

c# - SolrNet连接说明

c# - 限制 Unity 正交相机平移运动

c# - 应该在 Repository 或 Service 层编写复杂的查询?

c# - Entity Framework 查询以获取子项

C# 泛型、接口(interface)和继承

ios - 如何根据 Swift 中的字符串创建对象?

c# - 具有透明状态栏的 Xamarin Forms 背景图像

c# - 如何在控制台应用程序中为 Entity Framework 设置连接字符串

java - 如何使用流编写模式方法

c# - 带有 C# 扩展函数的 XSLT 中的错误消息