我有一个外部库中的类对象,我想向其中添加一些其他属性。
假设外部类是:
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;
如果您实际上可以扩展将很容易实现的External类:
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;
}
}
这当然可以通过继承来完成。考虑以下内容。
//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;}
//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()
{
}
}
几件事要知道:
是,继承是您要寻找的:
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() { }
}
如果您希望(或需要)委派而不是副本,则可以执行:
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;
}
}
代替使用特定类型,而是使用接口。
[下面,我展示facade pattern和adapter pattern的混合,以将外部数据“转换”为定义明确的接口(IDocument
),有效地抽象您正在处理的事情。
示例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);
}
}
}
}
Notes
继承的问题是,这是一个非常严格的方法,通常,一旦您开始做它,并且在某个时候碰壁并想还原,就很难摆脱它。
通过反对抽象,事情变得更加灵活,事物之间解耦了。
以下是两个可能促使您改变方法的示例: