• Castle与Mixin


            Mixin是一种将某个类中的方法混入其他类中的软件开发风格。简单的说,就是一个类可以使用其他类的方法。这个初听起来有点像类的继承,但是这与传统的类继承的方式不一样。
            首先,Mixin不是类的继承。传统的,一个类A继承了某个类B,那么A就可以直接调用B中的非private的方法。但是在Mixin中,A与B没有继承关系,而A却能使用B的非private的方法。
            其次,Mixin的这些行为是在运行时发生的,而不是静态指定的。

            下面是一个来自Python的Mixin的例子:
    John 翻著新的一期 LJ(Linux Journal) 

    [John@mars /tmp]# vi Lover.py 

    class lover:
        def __init__(self,man='man',woman='woman'):
            self.lover='When a '+man+' love a '+woman
            print self.lover
        def smile(self):
            print self.lover+':-)'
        def kiss(self):
            print self.lover+':-)(-:'


    [John@mars /tmp]# python
    Python 2.1 (#1, Apr 18 2001, 17:55:45)
    [GCC 2.95.3 19991030 (prerelease)] on linux2
    Type "copyright", "credits" or "license" for more information.

    >>>from Lover import lover

    >>>John_and_Rose=lover()
    When a man love a woman

    >>>John_and_Rose.smile()
    when a man love a woman:-)

    >>>John_and_Rose.kiss()
    when a man love a woman:-)(-:

    >>>John_and_Rose.sayGoodBye()
    Traceback (most recent call last):
      File "", line 1, in ?
    AttributeError: lover instance has no attribute 'sayGoodBye'

    >>>John_and_rose.JohnAskWhy()
    Traceback (most recent call last):
      File "", line 1, in ?
    AttributeError: lover instance has no attribute 'JohnAskWhy'

    >>>class RoseLoveSomebodyElse:
       def sayGoodBye(self):
           print "Let's say goodbye tonight."

    >>>lover.__bases__+=(RoseLoveSomebodyElse,)

    >>>John_and_Rose.sayGoodBye()
    Let's say goodbye tonight.
    >>>

    练习完 Using Mix-ins with Python 之後, 
    John 在闪著 >>> 的萤幕前大声地哭了起来。 

            注意,Python代码中的class RoseLoveSomebodyElse之后的代码,John定义了一个类,并将这个类与lover执行了Mixin,之后,lover具备了sayGoodBye的能力。
            这就是Mixin的威力。
            在学习Castle中,我发现Castle也具有Mixin的能力,所以,我模仿上面Python的例子,利用Castle尝试了Mixin。
            当然,C#不能像Python那样动态的执行以及支持多重继承,因此,我对上面的代码作了改动,使之适应C#。

            首先,我定义了一个类Lover及其接口ILover:
    public interface ILover
    {
        
    void Smile();
        
    void Kiss();
        
    void SayGoodbye2Lover();
    }


    public class Lover:ILover
    {
        
    private string _Lover = "";
        
        
    public Lover(string man, string woman)
        
    {
            _Lover 
    = "When " + man + " love " + woman;
            WL(_Lover);
        }

        
        
    public void Smile()
        
    {
            WL(_Lover 
    + " :-)");
        }

        
        
    public void Kiss()
        
    {
            WL(_Lover 
    + " :-)(-:");
        }

        
        
    public void SayGoodbye2Lover()
        
    {
            
    throw new System.NotSupportedException("We can not Say Goodbye");
        }

    }

            与Python代码不同的是,我多增加了一个SayGoodbye2Lover的方法。

            然后,我再定义了一个LoverLoveSomebodyElse及其接口ILoverLoveSomebodyElse,这个类对应Python例子中的RoseLoveSomebodyElse类。
    public interface ILoverLoveSomebodyElse
    {
        
    void LoverChangedMind(string who, string somebody);
        
    void SayGoodbye();
    }


    public class LoverLoveSomebodyElse:ILoverLoveSomebodyElse
    {
        
    private string _Who;
        
    private string _Somebody;
        
        
    public LoverLoveSomebodyElse()
        
    {
        }

        
        
    public void LoverChangedMind(string who, string somebody)
        
    {
            _Who 
    = who;
            _Somebody 
    = somebody;
        }

        
        
    public void SayGoodbye()
        
    {
            WL(_Who 
    + " changed mind and loved " + _Somebody);
            WL(
    "So ");
            WL(
    "Let's say goodbye tonight");
        }

    }

            随后,定义了一个Matchmaker类,这只是一个普通的类,不起任何作用。主要是为了创建代理用。
    public class Matchmaker
    {
        
    public Matchmaker()
        
    {
        }

        
        
    public virtual void Match()
        
    {
        }

    }

            好了,现在可以利用这三个类测试Mixin。这里主要对两个类测试Mixin:Lover和LoverLoveSomebodyElse

            在执行函数中输入如下代码:
    public static void Main()
    {
        
    try
        
    {
            WL(Environment.CurrentDirectory);
            GeneratorContext context 
    = new GeneratorContext();
            Lover lover 
    = new Lover("Wu Da Lang""Qin Xiang Lian");
            LoverLoveSomebodyElse changedMindLover 
    = new LoverLoveSomebodyElse();
            context.AddMixinInstance(changedMindLover);
            context.AddMixinInstance(lover);
                
            ProxyGenerator _generator 
    = new ProxyGenerator();
            
    object proxy = _generator.CreateCustomClassProxy(typeof(Matchmaker), new StandardInterceptor(), context);
                
            ILover lover_now 
    = proxy as ILover;
            lover_now.Smile();
            lover_now.Kiss();
                
            
    try
            
    {
                lover.SayGoodbye2Lover();
            }

            
    catch(System.NotSupportedException eX)
            
    {
                WL(eX.Message);
            }

                
            ILoverLoveSomebodyElse changedMindLover_now 
    = proxy as ILoverLoveSomebodyElse;
            changedMindLover_now.LoverChangedMind(
    "Pan Jin Lian""Xi Men Qing");
            changedMindLover_now.SayGoodbye();
        }

        
    catch(Exception eX)
        
    {
            WL(eX.Message);
            WL(eX.StackTrace);
        }

            
        RL();
    }

            执行后的结果如下:
    When Wu Da Lang love Pan Jin Lian
    When Wu Da Lang love Pan Jin Lian :-)
    When Wu Da Lang love Pan Jin Lian :-)(-:
    We can not Say Goodbye
    Pan Jin Lian changed mind and loved Xi Men Qing
    So 
    Let's say goodbye tonight

           就这样,proxy具备了Lover和LoverLoveSomebodyElse的所有可用的功能。

           很显然,从代码中可以看出,如果proxy是一个代码级的类的话,那么proxy继承了ILover和ILoverLoveSomebodyElse两个接口。正如我们在传统的给一个类添加行为的方法一样。

           例如,有一个类Foo,它只有一个方法:WriteMessage。如果我们想给Foo添加一个可选的Log行为,我们可以定义一个接口ILog,并给让Foo继承ILog,这样,Foo就变成了LoggableFoo了。

           Castle正是这样的做的。如我的另一篇Castle与动态代理中所说的,Castle创建一个类,这个类继承了ILover和ILoverLoveSomebodyElse接口,并使用Interceptor和Invocation织入Lover和LoverLoveSomebodyElse类的方法,从而使Proxy具备了两者的方法。

            使用Mixin可以让我们动态的决定哪些类在运行时可以具备哪些可选的功能。当然,由于C#不支持类多重继承,因此,我们必须要把能够Mixin的类抽象出接口。
  • 相关阅读:
    Less34-Less37 (宽字节注入)
    宽字节注入 Less32-Less33
    Less29(jspstudy)-Less31
    Less26-Less28a
    Less23-Less25a(24--二次注入)
    Less 11-22
    sqli-labs 1-10
    sqli-labs环境搭建与安装
    OSPF与ACL综合实例
    用分治法完成比赛操作
  • 原文地址:https://www.cnblogs.com/iaxes/p/133407.html
Copyright © 2020-2023  润新知