C# 继承已实例化的基本对象
是否可以执行以下操作:C# 继承已实例化的基本对象,c#,.net,inheritance,C#,.net,Inheritance,是否可以执行以下操作: public class ChildClass : BaseClass { public ChildClass(BaseClass o) { base = o; } } mySettingsProvider = new SettingsAuditor(mySettingsProvider); 基本上,我想要一种透明的方式将基类包装到其他功能中。我想到的一个例子是自定义设置提供程序,它透明地审核通过它传递的设置 public cl
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
基本上,我想要一种透明的方式将基类包装到其他功能中。我想到的一个例子是自定义设置提供程序,它透明地审核通过它传递的设置
public class SettingsAuditor : SettingsProvider
{
public SettingsAuditor(SettingsProvider o)
{
base = o;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
base.SetPropertyValues(context, propvals);
}
}
然后我可以做以下工作:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
所有更改在传递到原始对象之前都会经过重写的SetPropertyValues
我可以使用私有的设置Provider
成员,但是我不能从设置Provider
继承,或者根本不使用整个设置Provider
(基本
)
我正在使用C#4.0和.Net 4.0。否。这看起来应该是一个组合与继承的问题。你需要评估你是“是a”还是“有a”
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
没有,但你可以假装:
public class SettingsAuditor
{
SettingsProvider @base;
public SettingsAuditor(SettingsProvider o)
{
@base = o;
}
public void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
@base.SetPropertyValues(context, propvals);
}
}
注意这里,@base不是实际的base,只是一个名为base
base=o代码>
基。只要包装器实现与内部对象相同的接口或基类,就可以传回新包装器。您可以包装任意数量的装饰
考虑:
public interface ICar
{
void Drive();
}
public class Car : ICar
{
public void Drive()
{
Console.WriteLine("vroom");
}
}
public class BuckleUp : ICar
{
ICar car;
public BuckleUp(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("click!");
car.Drive();
}
}
public class CheckMirrors : ICar
{
ICar car;
public CheckMirrors(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("mirrors adjusted");
car.Drive();
}
}
现在考虑一个方法,接受一个<代码> ICAR 并告诉它驱动。你可以给它一辆
车
,它会工作的,但是你也可以把那辆车用BuckleUp
和CheckMirrors
包装起来,你根本不需要改变这个方法。您已经通过使用组合修改了功能。这不是一个完整的实现,使用表达式树可能会更简洁。。。但这是在.NET4.0中使用DynamicObject假装AOP的一次快速尝试
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
公共类MyDynamicRapper:DynamicObject
{
公共T包装{get;私有集;}
公共操作Pre{get;private set;}
公共操作Post{get;private set;}
公共MyDynamicRapper(T包装、动作前、动作后)
{
这个.包裹的=包裹的;
这个.Pre=Pre;
这个.Post=Post;
}
公共覆盖bool TryGetMember(
GetMemberBinder,
输出对象结果)
{
var类型=类型(T);
var method=type.GetMethod(binder.Name);
if(方法!=null)
{
Func Func=()=>
{
if(Pre!=null)
预包装;
//可以在此处添加对输入参数的支持
var ret=method.Invoke(包装,null);
如果(Post!=null)
邮政(包裹);;
返回ret;
};
结果=func;
返回true;
}
返回base.TryGetMember(活页夹,输出结果);
}
}
公共类MyDynamicRapper
{
公共静态MyDynamicRapper创建(
T拖缆,
Action pre=null,
操作(post=null)
{
返回新的MyDynamicRapper(牵引、前置、后置);
}
}
公共类MyObject
{
公共方法()
{
Console.WriteLine(“做点什么”);
}
}
班级计划
{
静态void Main()
{
var myobject=新的myobject();
dynamic mydyn=MyDynamicWrapper.Create(
我的对象,
p=>Console.WriteLine(“之前”),
p=>Console.WriteLine(“之后”);
//请注意,您没有智能。。。
//但是你可以在你之前使用旧的实现
//已更改为此包装版本。
mydyn.MyMethod();
/*输出低于
之前
做点什么
之后
*/
}
}
我理解设置编辑器
在技术上“有一个”设置Provider
,但我觉得它应该对开发者透明,应该像设置Provider
一样使用。另一个问题是套接字——通常,我编写的类“有一个”TcpSocket
,但它们公开了所有相同的方法,但有额外的逻辑,并且充当“TcpSocket
本身”
不适用于此解决方案。因此,您基本上希望有一种透明的方式来包装一个类,并允许通过新类重定向所有方法,而无需编写自定义方法?如果我理解正确的话,你可能想看看AOP或面向方面编程。我喜欢这种模式,但对于我不控制的基类(如SettingsProvider
和TcpSocket
),我唯一能继承的就是类本身,然后每次我都会被一个全新的基类所困扰,不能围绕一个现有的对象。@Daniel True,在某些情况下,它不会像密封类那样工作。但是,通常可以将所有调用重定向到装饰对象。例如,如果ICar
接口有一个int-miliege
属性,那么BuckleUp
和CheckMirrors
将分别实现如下属性:get{return car.miliege;}set{car.miliege=value;}
您可以对任何非密封类执行相同的操作,但是如果基类成员未声明为virtual
,则可能必须将成员声明为new
。目前,这不支持向方法提供参数。但这种支持可以很容易地添加。此外,如果将其更改为表达式树,您应该能够获得更好的类型和方法分辨率。