Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 继承已实例化的基本对象_C#_.net_Inheritance - Fatal编程技术网

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
    。目前,这不支持向方法提供参数。但这种支持可以很容易地添加。此外,如果将其更改为表达式树,您应该能够获得更好的类型和方法分辨率。