如何在c#中克隆类型T?

时间:2015-09-29 16:51:17

标签: c# types ormlite-servicestack

我有一个Foo类型如下:

[Alias("Boo")]
public class Foo
{
  public int Id { get; set; }
  public string Name { get; set; }
}

我正在保存对象属性更改的历史记录,出于性能原因,我想创建第二个表来推送所有历史记录。不幸的是,OrmLite不支持(afaik)每种类型的多个表。在定义时,将简单地使用别名而不是类型名称。

由于我使用的是通用数据控制器,我需要克隆实际类型 T(使用不同的名称Boo)。我不需要在两种类型之间转换/转换对象,但如果可能的话也会有所帮助。

4 个答案:

答案 0 :(得分:1)

"克隆"一个实例非常模糊:它是一个深层还是浅层的克隆?如果它很深,有多深?它是否包括对其他可能的POCO的引用?如果是这样,它将如何包含它们?使用id?使用副本?

此外,将对象的完整副本存储在不同的表中并不是实现历史记录的方法。

如果我是你,我可以使用不同的类型来存储序列化的更改,然后在您的实体中列出更改。

这是我在POCO中为最近的一些项目实现的方法(使用实体框架进行持久化,根据OrmLite的需要进行调整......还删除了一些内容):

/* BaseEntity just adds "Id" and some other properties common to all my
   POCOs */
public class EntityHistory : BaseEntity
{
  /* ... Other properties removed for clarity ... */
  public Guid TransactionId { get; set; }
  public DateTime TransactionTime { get; set; }

  public string OldValues { get; set; }
  public string NewValues { get; set; }
}

然后有一个基本实体(或一个接口,我使用一个基本实体,因为我不需要额外的多重继承,并且不让我在所有类中编写相同的属性),因为那些需要存储的实体历史:

public abstract class BaseTrackedEntity : BaseEntity, IAuditableEntity, IChangeTrackedEntity
{
  /* ... Other properties removed for clarity ... */
  public ICollection<EntityHistory> Histories { get; set; }
}

然后您的实体将继承BaseTrackedEntity

在对数据库进行持续更改后,您可以找到相应的更改(在EF中很容易,这会给您ChangeSet,但不了解OrmLite,但是如果它没有提供方法,你可以使用反射来完成它,从你加载的实体到保存的实体,并将它们序列化为EntityHistory实例(在OldValues和{ {1}})并将其添加到NewValues列表中。我使用JSON但你可以使用任何东西。

这适用于日志记录目的(我还没有复制我的日志记录属性 - 例如HistoriesUser和东西 - 但是它们都在{{1 }}和CreationTimeBaseTrackedEntity组中的Undoing如果需要撤消阶段),它非常高效(远远超过克隆和存储整个对象一次)每次更新),并且易于实施和维护。

答案 1 :(得分:0)

您可以添加并实施IClonable<T>吗?

interface ICloneable<T>
{
  T Clone();
}
[Alias("Boo")]
public class Foo : ICloneable<Foo>
{
  public int Id { get; set; }
  public string Name { get; set; }
  public Foo Clone() { ... }
}

答案 2 :(得分:0)

您可以使用继承来克隆定义

答案 3 :(得分:0)

解决方案变得比我更容易 - 虽然开头没有想到我的想法:继承!

由于我无法控制Foo类,因此我不能手动编写新类型来反映它(成员可能会在Foo中更改)。创建一个继承自Boo而没有定义额外成员的新类型Foo将允许使用OrmLite使用新名称创建和创建表。

public class Foo
{
  public int Id { get; set; }
  public string Name { get; set; }
}

public class Boo : Foo
{

}