我遇到了一个有点人为的编码问题,我希望有人可以告诉我,在标准C#中我能做什么是可能的。
我有一个类,它最初存储了Foo
个对象的列表,并对它们进行了更新,如下所示:
public class Program
{
private List<Foo> listOfFoo;
...
public void SomeMethod()
{
var fooObject = (Foo)(listOfFoo[0]);
fooObject.Name = "name";
fooObject.Address = "address;"
}
}
然后,我希望将List<Foo>
替换为自定义类FooRepository
,该类使用从FooDto
生成的Foo
类型的对象的支持列表,而不进行任何操作更改调用代码中listOfFoo
的使用方式:
public class FooRepository : IEnumerator<Foo>, IEnumerable<Foo>
{
private List<FooDto> backingList;
...
public void Add(Foo foo)
{
backingList.Add(MapToDto(foo));
}
public Foo this[int i]
{
get
{
return MapFromDto(backingList[i]);
}
}
...
}
但这会导致最初如何在调用代码中执行对象更新的问题,因为现在访问存储库不会返回对支持列表中的实际对象的引用,而是返回新生成的对象。所以我的问题是:保持这个基本设计,而不是在调用代码或Foo
本身中修改任何内容,我可以以某种方式修改FooRepository
,以便SomeMethod
中的更新仍然永久提交到存储库?
我可以在FooRepository
中存储两个列表,一个用于FooDto
,一个用于Foo
,并将Foo
列表中的更改提交到{{1}每次有人在存储库上调用方法时,我们假设我不想这样做。似乎我的基本策略是对存储库的所有访问都应返回一个可被视为FooDto
的对象,但它还具有将属性赋值提交给后备Foo
的附加行为。如果C#支持任意运行时猴子修补,我可以做类似的事情:
FooDto
但事实并非如此。我想过使用System.Reflection.Emit生成一个新的子类public Foo this[int i]
{
get
{
return MapFromDto(backingList[i]).ForAllProperties(property =>
{
property.NewSetter(value => backingList[i].property = value; ...);
}
}
}
来覆盖属性setter,但Foo
中的所有属性都没有标记为虚拟,所以我相信不能完成。我可以构造一个动态对象来实现Foo
中的所有内容以及新的setter行为,并使用像ImpromptuInterface这样的库将动态对象视为实现某个接口,但Foo
不实现任何接口;这些属性只是在类本身中编码。
似乎是在不修改调用代码或Foo
的情况下实现我想要的唯一方法就像this那样修改Foo
方法的IL代码在运行时。我有这个权利吗?我忽略了任何选择吗?
感谢。