【问题标题】:How to assign to all class data members at once如何一次分配给所有类数据成员
【发布时间】:2015-10-29 04:42:14
【问题描述】:

在 Dapper ORM 应用程序中,我想将一个对象分配给另一个对象,或者一次分配给所有数据成员。像这样:

public class TableA
{
    public int    UserId   { get; set; }
    public string ClientId { get; set; }
    // ... more fields ...

    public bool Query()
    {
        bool Ok = false;
        try{
            // Method A
            TableA Rec = QueryResultRecords.First(); 
            MyCopyRec(Rec, this);                        // ugly

            // Method B
            this = QueryResultRecords.First();           // avoids CopyRec, does not work

            Ok = true;
        }
        catch(Exception e){
            Ok = false;
        }
        return Ok;
    }
}

使用方法A可以将.First()中的对象直接赋值给class TableA的新对象,需要自定义方法MyCopyRec来获取同一个类的数据成员中的数据。

但是,使用方法 B,您不能将同一对象直接分配给 this

或者有其他方法吗?

【问题讨论】:

  • 为什么不直接将方法设为静态并从Query 返回TableA?将数据访问方法放在这些方法正在检索的模型中也被认为是糟糕的设计。 "Separation of concerns" 告诉我们 Query 应该在一个单独的类中。
  • 也许使用 AutoMapper?
  • @ScottChamberlain 这当然是一个选项,但我的示例代码被简化了。我的问题是是否有一个简单的方法B来编写一个类方法,将查询结果直接留在类数据成员中。
  • @DerreckDean 您是否暗示 C# 中没有简单的内置方法可以执行类似 MethodB 的操作,而这就是创建 AutoMapper 工具的原因?
  • 不,没有办法将所有属性从一个对象复制到另一个内置到.Net的对象。您可以编写一个使用反射来循环和复制属性的扩展,这基本上是 AutoMapper 所做的。然而,这引出了一个问题:你的对象真的有这么多属性,而为它们写target.Property = source.Property 会很痛苦吗?反思的开销不仅仅是把你的鼻子放在磨刀石上并输入作业。我的 0.02 美元。

标签: c# object


【解决方案1】:

如果“this”是引用类型,则不能将对象分配给“this”,例如一类。 “this”是指向当前类实例的指针。 这仅在这是一个值类型时才有效,例如一个结构体。

您只能为“this”的属性赋值(这可能发生在 (CopyRec 方法) 中,例如:

var result = QueryResultRecords.First();
this.UserId  = result.UserId;

【讨论】:

  • 你一定是对的,但我认为我的 Class 是一个结构。当然一个类可以有数据成员和方法,但是给方法赋值是没有意义的。所以太糟糕了,我不能将对象的 DATA 值分配给this。这是 C# 中缺少的功能,DataMapper 对此进行了修复吗?
【解决方案2】:
/// <summary>
/// Extension for 'Object' that copies the properties to a destination object.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="destination">The destination.</param>
public static void CopyProperties(this object source, object destination)
{
    // If any this null throw an exception
    if (source == null || destination == null)
        throw new ArgumentException("Source or/and Destination Objects are null");
    // Getting the Types of the objects
    Type typeDest = destination.GetType();
    Type typeSrc = source.GetType();

    // Iterate the Properties of the source instance and  
    // populate them from their desination counterparts  
    PropertyInfo[] srcProps = typeSrc.GetProperties();
    foreach (PropertyInfo srcProp in srcProps)
    {
        if (!srcProp.CanRead)
        {
            continue;
        }
        PropertyInfo targetProperty = typeDest.GetProperty(srcProp.Name);
        if (targetProperty == null)
        {
            continue;
        }
        if (!targetProperty.CanWrite)
        {
            continue;
        }
        if ((targetProperty.GetSetMethod().Attributes & MethodAttributes.Static) != 0)
        {
            continue;
        }
        if (!targetProperty.PropertyType.IsAssignableFrom(srcProp.PropertyType))
        {
            continue;
        }
        // Passed all tests, lets set the value
        targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
    }
}

这是我在上面的 cmets 中谈到的那个方法。

另请参考此链接:Apply properties values from one object to another of the same type automatically?

【讨论】:

  • 感谢您的代码示例,我一定会学习的。目前,我确信 C# 缺少分配给 this 的功能,而与 stackoverflow.com/a/18285160/1845672 中的一种单独的服务类一起使用更像是 C# 的精神,这就是我接受另一个的原因在这里回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
相关资源
最近更新 更多