使用附加属性扩展类
我有一个外部库的类对象,我想添加一些附加属性。使用附加属性扩展类
假设外部类:
public class ExternalClass
{
public string EXproperty1 {get;set;}
public string EXproperty2 {get;set;}
public string EXproperty3 {get;set;}
public ExternalClass(){}
}
和我有被填充为
List<ExternalClass> listOfExternalClass=new List<ExternalClass>();
listOfExternalClass=GetListOfExternalClass();
我可以通过创建一个新的类继承这个类,这些对象的列表,添加附加属性并使外部类成为属性。
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
但受外部类的原始列表转换为新类的列表,我将不得不创造新类一个新的列表,并通过原始列表创建一个新的对象,并将其添加到迭代列表,像
List<NewClass> listOfNewClass=new List<NewClass>();
foreach(var externalClass in listOfExternalClass)
{
listOfNewClass.Add(new NewClass(externalClass));
}
我会再能访问诸如
listOfNewClass.FirstOrDefault().ExternalClass.EXproperty1;
我能做到这一点与继承或者是有一个更有效的方法外部性?
理想我想通过调用类的属性直到结束:
listOfNewClass.FirstOrDefault().EXproperty1;
如果你实际上可以扩展外部类很容易实现:
public class NewClass: ExternalClass
{
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
// you would have to copy all the properties
this.EXproperty1 = externalClass.EXproperty1;
}
}
这就是我开始做的,但有太多的属性可以映射。如果外部类中的任何属性发生更改或被添加/删除,这也将证明是有问题的。 – DeclanMcD
啊哈,也许是完全动态的东西,但这可能证明太复杂:http://stackoverflow.com/questions/3810488/adding-a-property-to-an-existing-class –
或自动复制所有属性请参阅:http ://stackoverflow.com/questions/930433/apply-properties-values-from-one-object-to-another-of-the-same-type-automaticall –
是继承是你在找什么:
public class ExternalClass
{
public string EXproperty1 { get; set; }
public string EXproperty2 { get; set; }
public string EXproperty3 { get; set; }
public ExternalClass() { }
}
public class NewClass:ExternalClass
{
public string NewProperty1 { get; set; }
public string NewProperty2 { get; set; }
public NewClass() { }
}
这当然可以通过继承来完成。考虑以下。
//Inherit from our external class
public class NewClass: ExternalClass
{
//Note we do not have a copy of an ExternalClass object here.
//This class itself will now have all of its instance members.
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
//Base will call the constructor for the inherited class.
//If it has parameters include those parameters in NewClass() and add them to base().
//This is important so we don't have to write all the properties ourself.
//In some cases it's even impossible to write to those properties making this approach mandatory.
public NewClass(): base()
{
}
}
几件事情需要知道:
- 你的代码称为包装。这是因为它“包装”了另一班或一组班级。
- 您不能从标记为密封的类继承。
- 在C#中,类默认情况下是不封装的。如果他们被封闭,开发人员会故意阻止你继续从课程中继承。这通常是有原因的。
如果您希望(或需要)代表团,而不是一个副本,你可以这样做:
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public string EXproperty1 {get { return this.ExternalClass.EXproperty1; };set{ this.ExternalClass.EXproperty1 = value; }; }
public string EXproperty2 {get { return this.ExternalClass.EXproperty2; };set{ this.ExternalClass.EXproperty2 = value; }; }
public string EXproperty3 {get { return this.ExternalClass.EXproperty3; };set{ this.ExternalClass.EXproperty3 = value; }; }
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
+1这就是我忙于打字和赞美@ Licht的答案,通过填写课程封闭时可以做什么。唯一的缺点是缺乏多态性。 –
,而不是针对特定类型,对接口的工作工作。
下面我显示为“变换”外部数据到定义良好的接口(IDocument
)的facade pattern和adapter pattern混合,有效抽象的东西你正在努力。
例1:约界面查询
这里是你的工作对类型:
public interface IDocument {
string Name { get; set; }
}
public interface IMetadata {
string[] Tags { get; set; }
}
这是你自己的表现,如果你需要任何:
public class RichDocument : IDocument, IMetadata {
public string Name { get; set; }
public string[] Tags { get; set; }
}
这是对外部数据的包装:
(正面和/或适配器的杂种混合概念)
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalDocument : IDocument /* only a basic object */ {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass @class) {
_class = @class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
以及如何使用所有演示:
internal class Demo1 {
public Demo1() {
var documents = new List<IDocument> {
new ExternalDocument(new ExternalClass()),
new RichDocument()
};
foreach (var document in documents){
var name = document.Name;
Console.WriteLine(name);
// see if it implements some interface and do something with it
var metadata = document as IMetadata;
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
实施例2:关于组件
查询通过推动概念以统一的方式处理所有事情,你可以在.NET框架,游戏开发或其他任何东西中找到它......
你会工作对定义:
public interface IContainer {
IList<IComponent> Components { get; }
}
public interface IComponent {
// it can be/do anything
}
一些组件你查询一下:
public interface IDocument : IComponent {
string Name { get; set; }
}
public interface IMetadata : IComponent {
string[] Tags { get; set; }
}
你的 '内部' 类型:
public class Container : IContainer {
public Container() {
Components = new List<IComponent>();
}
public IList<IComponent> Components { get; }
}
你 '包装' 免受外部数据:
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalContainer : IContainer {
private readonly List<IComponent> _components;
public ExternalContainer(ExternalClass @class) {
_components = new List<IComponent> {new ExternalDocument(@class)};
}
public IList<IComponent> Components {
get { return _components; }
}
}
public class ExternalDocument : IDocument {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass @class) {
_class = @class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
以及使用例如:
public class Demo2 {
public Demo2() {
var containers = new List<IContainer> {
new ExternalContainer(new ExternalClass()),
new Container()
};
foreach (var container in containers) {
// query container for some components
var components = container.Components;
var document = components.OfType<IDocument>().FirstOrDefault();
if (document != null) {
Console.WriteLine(document.Name);
}
var metadata = components.OfType<IMetadata>().FirstOrDefault();
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
注意
与继承的问题是,它是一个非常严格的办法,通常一旦你开始这样做,并在某些时候,你碰了壁,并希望要恢复,很难摆脱它。
通过解决抽象问题,事情更加灵活,事物解耦。
这里有两个例子,可能煽动你改变你的做法:
你是对的,组合(或委托)在很多情况下都是可行的,但是你的类型层次结构为一个简单的问题带来了巨大的复杂性。总是KISS(https://en.wikipedia.org/wiki/KISS_principle),直到你确实需要使用不同类型的对象。 –
你是100%的权利。我告诉人们的东西,但大部分时间都忘了自己做 – Aybe
为什么不inheretance?你已经尝试过了吗? –
这就是这样的问题总是会导致多个答案,都是一样的 – MickyD
您可能想阅读[Eric Lippert关于monads的博客系列](https://ericlippert.com/2013/02/21/monads-part-one) 。 – OldFart