动态实现接口

  一般来说,接口只能在编码时实现,但由于某些原因,无法在运行时实现。下面就介绍一种在运行时实现接口的解决方案。

  在介绍之前,先学习这个方案中所需要的知识点是动态编译委托反射

分析:
    1、实现接口还是必须有一个类,一个“class ClassName : InterfaceName {...}”的类。顺着这个思路,会想到这个ClassName能否动态生成(运行时生成)。

    2、动态生成类,有两种方式:动态编译Emit技术(这里使用“动态编译”)。如果每实现一个类都需要动态编译,这样一定承担上影响性能,也占内存。所以思考这个类能不能是一个“模版类”,一个接口对应一个“动态实现的模版类”(当然,不同接口肯定是对应不同的“动态实现的模版类”),不同的实现,由你自己决定。

    3、“动态实现的模版类”会想到委托。如:

public class ClassNameImplementTemplate : InterfaceName
{
    private Dictionary<string, Delegate> _implements;  // 具体实现的委托

   // 实现接口的方法
public void Func()
  {
    // 这里执行
_implements["Func"]的Delegate

  }

}

      在“动态实现的模版类(ClassNameImplementTemplate)”里维护一个具体实现列表,也就是一个委托列表。在“动态实现的模版类”中的实现接口的方法里,去对应执行这个委托列表的具体实现委托。

  通过上面的分析,总结思路,步骤如下:

    1、通过“动态实现接口”生成“动态实现的模版类”。

    2、用户具体实现属性、方法、事件等。

    3、用户实例化“动态实现的模版”对象。

  按照上次的步骤,我们对其进行封装:RuntimeClass<Interface>类。类图如下:

      

  该类包含了生成“动态实现的模版类”、用户实现方法、用户实现属性、用户触发事件(可在实现属性或方法中触发事件)以及最后的实例化。当用户需要动态实现接口ITry时,可用下面代码:

    public interface ITry
    {
        string Prop1
        {
            get;
            set;
        }

        event EventHandler Click;

        string Fun2();
    }

    RuntimeClass<ITry> cls = new RuntimeClass<ITry>();
    cls.ImplementProperty<string>("Prop1",           // 具体实现Prop1属性
         (@this) =>                                  // @this是实例本身,这样即可调用实例的其他方法或访问属性或触发事件
         {
// 相当于属性的get
return cls.Fields["prop1"].ToString(); // 字符 }, (@this, s) => {
        // 相当于属性的set cls.Fields[
"prop1"] = s; }).ImplementMethod("Fun2", new Func<ITry, string>((@this) => // 具体实现Fun2方法 { cls.OnEventHandler(@this, "Click", null, EventArgs.Empty); //触发事件 @this.Prop1 = "3212"; return @this.Prop1; })
); ITry obj
= (ITry)cls.CreateInstance();// 实例化 obj.Click += (sender, e) => // 注册事件 { MessageBox.Show("点击"); }; obj.Prop1 = "123";      // 属性赋值 string ss = obj.Prop1; // 获取属性 ss = obj.Fun2(); // 执行方法

VS2010,.net4 代码下载: http://download.csdn.net/detail/lyb018/4685241

 

  通过这种解决方案,可以扩展出动态代理、拦截器等等。

posted @ 2012-10-25 11:54  Lemap  阅读(4689)  评论(6编辑  收藏  举报