I am trying to create a class hierarchy where a BaseClass.GetCopy()
method would provide copies of the same runtime subclass, with the same readonly ID property (passed via constructor), and with every public writeable property copied.
I got the code below, but the tests don't pass, since I didn't know how to implement reflection-based property copying. Also, the constructors in base class became duplicated (error-prone, IMO), and the parameterized one is public, which is not a good thing in this case, since I don't want the client code to be able to set Ids explicitly.
My questions are stated as comments in the code below:
[TestFixture]
public class RepoItemTests
{
[Test]
public void CloneHasSameId()
{
var one = new ConcreteRepoItemName();
var two = one.GetCopy();
Assert.AreEqual(one.Id, two.Id);
}
[Test]
public void CloneIsSubclassInstance()
{
var one = new ConcreteRepoItemAge();
var two = one.GetCopy();
Assert.IsInstanceOf<ConcreteRepoItemAge>(two);
}
[Test]
public void ChangingCloneNameDoesntChangeOriginalAge()
{
var one = new ConcreteRepoItemName() { Name = "original" };
var two = one.GetCopy() as ConcreteRepoItemName;
Assert.AreEqual(one.Name, two.Name);
two.Name = "modified";
Assert.AreNotEqual(one.Name, two.Name);
}
[Test]
public void ChangingCloneAgeDoesntChangeOriginalAge()
{
var one = new ConcreteRepoItemAge() { Age = 22 };
var two = one.GetCopy() as ConcreteRepoItemAge;
Assert.AreEqual(one.Age, two.Age);
two.Age = 33;
Assert.AreNotEqual(one.Age, two.Age);
}
}
public class ConcreteRepoItemName : AbstractRepoItem<ConcreteRepoItemName>
{
public ConcreteRepoItemName() : base() { }
// I don't want the constructor below to be public
public ConcreteRepoItemName(Guid id) : base(id) { }
public string Name { get; set; }
}
public class ConcreteRepoItemAge : AbstractRepoItem<ConcreteRepoItemAge>
{
public ConcreteRepoItemAge() : base() { }
// I don't want the constructor below to be public
public ConcreteRepoItemAge(Guid id) : base(id) { }
public decimal Age { get; set; }
}
public abstract class AbstractRepoItem<T> where T : AbstractRepoItem<T>, new()
{
public AbstractRepoItem()
{
Id = Guid.NewGuid();
}
// I don't want the constructor below to be public
protected AbstractRepoItem(Guid id)
{
Id = id;
}
public Guid Id { get; private set; }
public T GetCopy()
{
var clone = Activator.CreateInstance(typeof(T), new object[] { Id }) as T;
/// HOW DO I COPY RUNTIME PROPERTIES HERE VIA REFLECTION?
return clone;
}
}
Aucun commentaire:
Enregistrer un commentaire