c#覆盖/添加方法/字段到对象
本文关键字:对象 字段 添加 覆盖 方法 | 更新日期: 2023-09-27 18:14:01
我有一个为我创建和设置对象的库,然后我可以使用这些对象来做事情。
假设给定a类的对象a
所以我想在特定的对象中重写一个方法,我不想改变它的类的代码,因为那需要改变库。
在Ruby中,我可以使用单例类来做到这一点,比如:class FirstClass
def test
p "test"
end
end
o = FirstClass.new
class << o
def test
p "overridden"
end
def extraMethod
p "ok"
end
end
o.test # prints "overridden"
o.extraMethod
现在我如何在c#中做同样的事情?
我最终没有使用我提交的答案,因为它太丑了,它需要改变基类中的所有私有字段来保护或公共,以使它们存在于派生类中,因此我可以从基类复制值到派生。
我最终使用的方法是将从基类派生的Type传递给库并更改库,以便使用
创建实例:(A)Activator.CreateInstance(mytype, arguments);
c#不(直接)支持类型的运行时扩展,除非通过dynamic
机制。
最接近的选项可能是使用ExpandoObject
和dynamic
:
dynamic o = new ExpandoObject();
o.a = 10;
o.ExtraMethod = new Action( () => Console.WriteLine("ok") );
// Invoke
o.ExtraMethod();
话虽这么说,但这并不是c#的典型工作方式。
在c#中可以通过使用delegate
在运行时"重写方法"(注意引号)public class SomeClass
{
public SomeClass()
{
//set the default
OverridableMethod = () => MessageBox.Show("Default!");
}
public void StandardMethod()
{
//Call it.
OverridableMethod();
}
public Action OverridableMethod {get;set;}
}
用法:
var some1 = new SomeClass();
some1.StandardMethod(); //Shows "Default!"
some1.OverridableMethod(); //Shows "Default!"
var some2 = new SomeClass {OverridableMethod = () => MessageBox.Show("Override!!")};
some2.StandardMethod(); //Shows "Override!"
some2.OverridableMethod(); //Shows "Override!"
实际上有一种难看的方法。
我想使用继承和向下转换,但向下转换是无效的。但是,您可以使用反射来达到相同的结果。
static void Main()
{
A a = new A();
a.FieldA = 999; // change the object
a.test(); // "This is A and FieldA is 999"
//B b = (B)a; // => Error: Invalid you cannot downcast !
// using reflection we turn "a" into an instance of B that is a copy of the old "a"
a = new B(a);
a.test(); // This will call the method in B: "Calling the new method" "This is B and FieldA is 999 and FieldB is 10"
// a.newMethod(); => Error cannot access this method because "a" is declared as an instance of A (even though it's actually of B now)
B b = (B)a; // Now downcasting works fine (because A is an instance of B actually)
b.newMethod(); // works as expected: "This is B and FieldA is 999 and FieldB is 10"
}
class A
{
public int FieldA;
public A()
{
FieldA = 100;
}
virtual public void test()
{
Console.WriteLine("This is A and FieldA is {0}", FieldA);
}
}
class B : A
{
int FieldB;
public B(A a)
{
// copy all fields
foreach (FieldInfo pi in typeof(A).GetFields())
GetType().GetField(pi.Name).SetValue
(this, pi.GetValue(a));
// add this field:
FieldB = 10;
}
// We can override methods
override public void test()
{
Console.WriteLine("Calling the new method:");
newMethod();
}
// Add a new method but it will only be visible after casting A to B
public void newMethod()
{
Console.WriteLine("This is B, FieldA is {0} and FieldB is {1}", FieldA, FieldB);
}
}
所以我已经覆盖了"a"中的方法,并添加了新的字段。
我意识到这并不能实现与Ruby中相同的功能,但至少我可以覆盖方法并添加可以在我覆盖的方法中使用的方法/字段。