是否可以执行以下操作:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
基本上,我想要一种透明的方法将基类包装在其他功能中。我想到的一个例子是自定义设置提供程序,它透明地审核通过它的设置。
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);
}
}
然后我可以做以下事情:
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
在传递给原始对象之前,所有更改都将通过被覆盖的SetPropertyValues
。
我可以使用私人SettingsProvider
成员,但是我要么无法继承 SettingsProvider
中的,要么拥有整个SettingsProvider
(base
)根本没用。
我正在使用C#4.0和.Net 4.0。
答案 0 :(得分:4)
base = o;
您只需包含内部成员,而不是尝试设置base
。只要包装器实现与内部对象相同的接口或基类,就可以传回新的包装器。您可以根据需要包装任意数量的装饰器。
考虑一下:
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
并告诉它开车。您可以给它一个Car
,它会起作用,但您也可以将该车包裹在BuckleUp
和CheckMirrors
中,您根本不需要更改该方法。您已使用Decorator Pattern修改了合成功能。
答案 1 :(得分:2)
没有。这看起来应该是一个Composition vs Inheritance问题。您需要评估自己是“是”还是“有”。
答案 2 :(得分:2)
这不是一个完整的实现,它可能可以用表达式树做得更干净......但是这是使用动态对象与.Net 4.0伪造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
*/
}
}
答案 3 :(得分:0)
不,但你可以伪造它:
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