Я не думаю, что AutoFixture может это сделать, но Albedo может. Хотя это всего лишь пробный код, я надеюсь, он должен проиллюстрировать общую идею.
Создайте новый класс, производный от ReflectionVisitor<T>
:
public class PropertyCopyVisitor<T> : ReflectionVisitor<T>
{
private readonly T source;
private readonly T destination;
public PropertyCopyVisitor(T source, T destination)
{
this.source = source;
this.destination = destination;
}
public override IReflectionVisitor<T> Visit(
PropertyInfoElement propertyInfoElement)
{
var pi = propertyInfoElement.PropertyInfo;
pi.SetValue(this.destination, pi.GetValue(this.source));
return this;
}
public override T Value
{
get { return this.destination; }
}
}
Ключевой частью реализации является перегрузка Visit
, где она использует Reflection для копирования каждого свойства из объекта source
в destination
.
Поскольку эта реализация изменяет destination
, свойство Value
никогда не используется, но оно должно присутствовать, потому что оно abstract
в _9 _...
Теперь вы можете написать свой тест как:
var fixture = new Fixture();
var a = fixture.Create<Foo>();
var b = fixture.Create<Foo>(); // Or just create a new, empty Foo...
// This copies all properties from a to b:
new TypeElement(typeof(Foo)).Accept(new PropertyCopyVisitor<Foo>(a, b));
Assert.False(ReferenceEquals(a, b));
Assert.Equal(a.Name, b.Name);
Здесь я все еще использовал fixture
для создания b
, но вам не нужно этого делать, потому что все свойства в любом случае будут перезаписаны. Если Foo
имеет конструктор без параметров, вы можете вместо этого просто использовать new Foo()
; это не имело бы значения.
Это доказательство концепции явно копирует только свойства. Если вам также нужно скопировать поля, вам также придется переопределить соответствующий метод Visit
. Кроме того, если рассматриваемые объекты принимают аргументы конструктора, вам также придется иметь дело с ними явно.
Если вам утомительно писать new TypeElement(typeof(Foo)).Accept(new PropertyCopyVisitor<Foo>(a, b));
, я уверен, что вы найдете способ написать вспомогательный метод для этого.
В качестве дополнительного примечания, PropertyCopyVisitor
не должен быть общим, потому что на самом деле он ни для чего не использует аргумент типа T
. Мне просто нравится безопасность типов, которую это дает конструктору ...
person
Mark Seemann
schedule
07.11.2017