除了从 sealed 类 继承之外,还有其他选择吗?
Is there an alternative to inheriting from sealed classes?
我问这个问题的原因是因为我想创建一个 class,它具有 FileInfo class(派生自 FileInfo)的所有功能,并允许我添加我的拥有它的属性。
我认为一个例子会更多地协作。
我想要的:
BindingList<FileInformation> files = new BindingList<FileInformation>();
public void GatherFileInfo(string path)
{
files.Add(new FileInformation(path));
listboxFiles.DataContext = files;
}
class FileInformation : FileInfo
{
public bool selected = false;
}
与我害怕我必须做的事情相比:
BindingList<FileInformation> files = new BindingList<FileInformation>();
public void GatherFileInfo(string path)
{
files.Add(new FileInformation(path));
listboxFiles.DataContext = files;
}
class FileInformation : FileInfo
{
string path = "<whatever>"
FileInfo fileInfo = new FileInfo(path);
public bool selected = false;
public string Name
{
get { return fileInfo.Name }
}
//Manually inherit everything I need???
}
这样做的好处是,在 WPF 中,您可以简单地绑定到 class FileInformation 的所有属性,包括那些继承的 FileInfo class.
我从来没有研究过这个问题,也不知道我应该从哪里开始寻找,所以一个例子或一个关于如何做到这一点的线索会很有帮助。
.Net 中确实没有办法从密封的 class 继承。您可以编写扩展方法,但这不允许您添加新的属性或字段。您唯一可以做的另一件事是模拟继承,但是制作您自己的 class,其中包含您要继承的 class 类型的字段,然后手动公开每个 属性和 "base" class 的方法,方法是为每个方法编写一个包装器方法。如果 class 很小,那还不错,但是如果 class 很大,那就很痛苦了。
我编写了代码生成器程序来使用反射自动为我执行此操作。然后我获取它的输出并扩展它。但这不是真正的继承。我个人不喜欢密封 classes 的概念,因为它会阻止扩展那些 classes。但我想他们这样做是出于性能原因。
由于 FileInfo
继承自 MarshalByRefObject
,您可以创建一个模仿 FileInfo
的自定义代理并处理您自己的实现中的所有调用。但是,您将无法转换它,更重要的是,您无法使用自定义属性扩展此类 class。无论如何,如果其他人想要这个,SharpUtils 有一些工具可以帮助它。
要继承 sealed class 尝试使用 Decorator 设计模式,
基本思想是创建 OldClass 的私有实例,并手动实现 all 它的方法,如:
public class NewClass
{
private OldClass oldClass = new OldClass();
public override string ToString()
{
return oldClass.ToString();
}
//void example
public void Method1()
{
oldClass.Method1();
}
//primitive type example
public int Method2()
{
return oldClass.Method2();
}
//chaining example, please note you must return "this" and (do not return the oldClass instance).
public NewClass Method3()
{
oldClass.Method3();
return this;
}
}
public class Demo
{
static void Main(string[] args)
{
var newClass = new NewClass();
newClass.Method3();
WriteLine(newClass);
}
}
我问这个问题的原因是因为我想创建一个 class,它具有 FileInfo class(派生自 FileInfo)的所有功能,并允许我添加我的拥有它的属性。
我认为一个例子会更多地协作。 我想要的:
BindingList<FileInformation> files = new BindingList<FileInformation>();
public void GatherFileInfo(string path)
{
files.Add(new FileInformation(path));
listboxFiles.DataContext = files;
}
class FileInformation : FileInfo
{
public bool selected = false;
}
与我害怕我必须做的事情相比:
BindingList<FileInformation> files = new BindingList<FileInformation>();
public void GatherFileInfo(string path)
{
files.Add(new FileInformation(path));
listboxFiles.DataContext = files;
}
class FileInformation : FileInfo
{
string path = "<whatever>"
FileInfo fileInfo = new FileInfo(path);
public bool selected = false;
public string Name
{
get { return fileInfo.Name }
}
//Manually inherit everything I need???
}
这样做的好处是,在 WPF 中,您可以简单地绑定到 class FileInformation 的所有属性,包括那些继承的 FileInfo class.
我从来没有研究过这个问题,也不知道我应该从哪里开始寻找,所以一个例子或一个关于如何做到这一点的线索会很有帮助。
.Net 中确实没有办法从密封的 class 继承。您可以编写扩展方法,但这不允许您添加新的属性或字段。您唯一可以做的另一件事是模拟继承,但是制作您自己的 class,其中包含您要继承的 class 类型的字段,然后手动公开每个 属性和 "base" class 的方法,方法是为每个方法编写一个包装器方法。如果 class 很小,那还不错,但是如果 class 很大,那就很痛苦了。
我编写了代码生成器程序来使用反射自动为我执行此操作。然后我获取它的输出并扩展它。但这不是真正的继承。我个人不喜欢密封 classes 的概念,因为它会阻止扩展那些 classes。但我想他们这样做是出于性能原因。
由于 FileInfo
继承自 MarshalByRefObject
,您可以创建一个模仿 FileInfo
的自定义代理并处理您自己的实现中的所有调用。但是,您将无法转换它,更重要的是,您无法使用自定义属性扩展此类 class。无论如何,如果其他人想要这个,SharpUtils 有一些工具可以帮助它。
要继承 sealed class 尝试使用 Decorator 设计模式, 基本思想是创建 OldClass 的私有实例,并手动实现 all 它的方法,如:
public class NewClass
{
private OldClass oldClass = new OldClass();
public override string ToString()
{
return oldClass.ToString();
}
//void example
public void Method1()
{
oldClass.Method1();
}
//primitive type example
public int Method2()
{
return oldClass.Method2();
}
//chaining example, please note you must return "this" and (do not return the oldClass instance).
public NewClass Method3()
{
oldClass.Method3();
return this;
}
}
public class Demo
{
static void Main(string[] args)
{
var newClass = new NewClass();
newClass.Method3();
WriteLine(newClass);
}
}