首先要注意的是 - 我知道委托(delegate)和装饰器模式!
第二 - 我正在使用 C# .NET 4.0,因此如果您想出一个专门针对它的解决方案,那很好。但如果解决方案适用于任何 OOP 语言和平台,那就太好了。
问题来了......
我有一个部分类(让我们将其命名为 Class1
),我无法修改它。因此,我可以扩展它或/并继承它。这个类为我提供了一个完美的数据模型,我唯一需要的就是向其属性添加一些属性(用于验证、在 MVC 中定义标签文本值等 - 目前,我不需要诸如“你可以做你想做的事”之类的答案需要没有属性”,这不是我的问题)。
使用另一个类作为数据模型不是问题,所以我可以创建 Class2 : Class1
并使用Class2
作为模特。需要属性的属性将定义为 public new <type> <propertyname>
。这将限制我只重写需要属性的属性,而其他所有属性保持不变。
较小的问题是我不需要重新定义属性的 getter 和 setter,因为它们将包含 return base.<propertyname>
和base.<propertyname> = value
,如果有很多这样的属性,这意味着很多“愚蠢”的编码。有办法避免这种情况吗?
更大的问题是我必须参数化我的 Class2
与 Class1
实例并制作类似 class2.<propertyname> = class1.<propertyname>
的内容对于我拥有的每个属性 - 太多的“愚蠢”编码。我可以使用反射来避免它 - 在 Class1
中查找具有公共(public) getter 和 setter 的所有属性并调用prop.SetValue(child, prop.GetValue(parent, null), null);
在循环。这为简单情况提供了一个通用函数,这非常好,因为我主要有简单的模型 - 许多具有公共(public) getter 和 setter 的属性,没有主体和其他逻辑。但我想要更通用的解决方案,而且我不喜欢反射。有什么想法吗?
这里是创建 Class2
的扩展方法的完整代码基于Class1
public static Child ToExtendedChild<Parent, Child>(this Parent parent)
where Child : Parent, new()
{
Child child = new Child();
var props = typeof(Parent).GetProperties().Where(p => p.GetAccessors().Count() >= 2);
foreach (var prop in props)
{
prop.SetValue(child, prop.GetValue(parent, null), null);
}
return child;
}
(顺便说一句,此方法可能无法理想地实现我的解决方案,因此任何更正也将不胜感激)
提前致谢!
最佳答案
较小的问题似乎不是什么大问题。也许我误解了这个问题,但假设您只是派生一个子类,则没有理由重新定义属性或其关联的 getter/setter。
更大的问题可以使用更简单的方法来解决。在许多对象初始化中使用反射似乎有点昂贵。如果您处理的类主要是一个大包或属性,也许您应该在任何给定情况下都需要访问所有这些属性。您提到 MVC 和验证,整个模型是否在您进行验证的 Controller 方法中使用?如果没有,为什么不考虑使用仅公开该方法中所需的那些部分的 View 模型呢?
你的反射初始化器很有趣,但是如果你要做很多这样的事情,那么你可能会考虑在Automapper上投入一些时间。 。否则,可以考虑从通用解决方案转向仅解决当前问题的解决方案,即将属性从对象的实例映射到派生对象的另一个实例。也许您可以在父类中创建一个复制构造函数并在派生类中使用它?
public class Foo {
public string PropOne { get; set; }
public string PropTwo { get; set; }
public Foo(string propOne, string propTwo) {
PropOne = propOne;
PropTwo = propTwo;
}
public Foo(Foo foo) {
PropOne = foo.PropOne;
PropTwo = foo.PropTwo;
}
}
public class Pho : Foo {
// if you have additional properties then handle them here
// and let the base class take care of the rest.
public string PropThree { get; set; }
public Pho(string propOne, string propTwo, string propThree)
: base(propOne, propTwo) {
PropThree = propThree;
}
public Pho(Pho pho) : base(pho) {
PropThree = pho.PropThree;
}
// otherwise you can just rely on a copy constructor
// to handle the initialization.
public Pho(Foo foo) : base(foo) {}
}
关于c# - 类扩展 - 最佳实践/最佳解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3646568/