【问题标题】:Is there a .NET equivalent syntax to Delphi's Assign/AssignTo?是否有与 Delphi 的 Assign/AssignTo 等效的 .NET 语法?
【发布时间】:2011-12-21 20:31:19
【问题描述】:

Delphi 有一个标准机制,可以从另一个对象复制一个对象,这里解释为:

class Persistent 
{
    protected AssignError(Persistent source)
    {
       throw new ConvertError("Cannot assign a {0} to a {1}", source.GetType().Name, this.GetType().Name);
    }

    protected virtual AssignTo(Persistent destination)
    {
        destination.AssignError(this);
    }

    public virtual Assign(Persistent source)
    {
       source.AssignTo(this);
    }
}

.NET FCL 是否具有在彼此之间复制对象的规范语法?

例如:

interface IPersistent
{
   public virtual Assign(Object source);
}

public class User : IPersistent
{
    private Image avatarThumbnail;
    private String name;

    public override Assign(Object source)
    {
       if (source is User)
       {
          this.avatarThumbnail = source.avatarThumbnail;
          this.name = source.Name;
       }
       else if (source is Image)
           avatarThumbnail = (Image)source;
       else if (source is DirectoryEntry)
           name = ((DirectoryEntry) source).Firstname + " " + ((DirectoryEntry) source).Lastname;
       else
           throw new AssignError("Assign from {0}", source.GetType());
    }
}

是的,我刚刚发明了一个标准的IPersistent 接口;但是是否已经有一种机制可以在彼此之间复制对象?

更新

注意:我说的是克隆对象的相反

User originalUser = new User();
User theClone = originalUser.Clone();
theClone.Lastname = "Guyer";

originalUser.Assign(theClone);

或者,我什至根本不需要克隆:

User u = new User();
u.Assign(salesOrder); //copy name/e-mail from the sales order

SalesOrder s = new SalesOrder();
s.SalesOrderDate = DateTime.Now;
User customer = new Customer("Kirsten");
s.Assign(user); //copy sold-to/ship-to information from the user

【问题讨论】:

  • 你是在 VS 中这样做还是在 Delphi 2010 中使用 Prism
  • 这取决于 - 您是否希望在遇到赋值语句时自动调用这些函数? (a la C++ 复制构造函数) - 如果是这样,答案是否定的。
  • @Damien_The_Unbeliever 不,调用databaseConnection.Assign(font) 可以正常工作(请记住,我将编写知道如何将字体复制到 DatabaseConnection 的逻辑)

标签: c# .net variable-assignment


【解决方案1】:

.NET 框架有ICloneable 接口:

支持克隆,即创建一个与现有实例具有相同值的类的新实例。

还有:

ICloneable 接口包含一个成员Clone,它旨在支持超出MemberwiseClone 提供的克隆。有关克隆、深拷贝与浅拷贝以及示例的更多信息,请参阅Object.MemberwiseClone 方法。


更新:

据我所知,在 BCL 中没有与您想要的(在不同对象之间复制 一些 值的标准方法)等效的东西。

【讨论】:

  • 请注意,该规范允许将Clone 实现为深拷贝或浅拷贝。所以,使用别人提供的ICloneable时要小心。
  • 奇怪的是你引用了ICloneable 接口,因为它是useless and considered obsolete。框架设计指南建议任何人使用它。与未实现 ICloneable 的对象上的 Clone 方法相比,它没有任何优势。
  • @Steven - MSDN 文档没有提到它已经过时。这也是最接近 OP 要求的东西。
  • 我指的不是克隆对象,因为严格来说,该系统允许将DbConnection 克隆为System.Drawing.Font
  • @Oded:ICloneable 接口究竟做了什么?它只是一个界面;您必须自己实现克隆,在这种情况下,与在没有该接口的情况下实现 Clone 方法相比,它不会增加任何价值。如果您建议 OP 使用ICloneable,您基本上是在说“自己创建一个克隆方法, which doesn't really help him :-). btw I didn't say ICloneable”标有ObsoleteAttribute,但它被认为已过时,因为框架设计指南建议不要使用它。
【解决方案2】:

作为标准 ICloneable 接口的替代方案,您可以使用反射执行公共属性/字段的复制。这是我为此写下的一些代码:

foreach(PropertyInfo mbr in src.GetType().GetProperties())
    mbr.SetValue(dst, src.GetValue(src, BindingFlags.GetProperty, null, null, null), BindingFlags.SetProperty, null, null, null)

foreach(FieldInfo mbr in src.GetType().GetFields())
    mbr.SetValue(dst, src.GetValue(src, BindingFlags.GetField, null, null, null), BindingFlags.SetField, null, null, null)

【讨论】:

  • 我已经克隆了 (stackoverflow.com/a/78612/12597)。现在的问题是将克隆复制回原件。
  • 这比使用MemberwiseClone 更好吗?
  • @Brian - 在很多方面并非如此。 “MemberwiseClone”是类似过程的本机实现。我发现自己实现它的唯一好处是在需要控制复制哪些字段和复制深度的利基情况下。不过,与此处的原始问题并不真正相关。
猜你喜欢
  • 2010-10-04
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2011-05-31
  • 2012-03-05
  • 2017-05-01
相关资源
最近更新 更多