代码之家  ›  专栏  ›  技术社区  ›  dlras2

继承已实例化的基对象

  •  2
  • dlras2  · 技术社区  · 14 年前

    是否可以执行以下操作:

    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 成员,但我也不能继承 设置存储 或者有一个完整的 设置存储 ( base )根本不用。

    我使用的是C 4.0和.NET 4.0。

    4 回复  |  直到 14 年前
        1
  •  4
  •   Jay    14 年前
    1. 你做不到 base = o;
    2. 你要找的是 Decorator Pattern 这是一种在运行时合成添加功能的方法(与继承相比)。

    而不是试图设置 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 和A CheckMirrors 你根本不需要改变这个方法。您已经使用 装饰器模式 .

        2
  •  2
  •   Nix    14 年前

    不。这看起来应该是一个组合与继承问题。您需要评估您是“是”还是“有”。

    A little help for your journey

        3
  •  2
  •   Matthew Whited    14 年前

    这不是一个完整的实现,它可能可以用表达式树做得更干净…但这是一个在使用带有.NET 4.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
            */
        }
    }
    
        4
  •  0
  •   James Curran    14 年前

    不,但你可以伪造它:

    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