• C#基础:泛型的接口抽象


        一个比较有趣的问题:某程序在启动之前,需要对三种不同类型的数据的交叉引用(Cross Reference,xref)进行更新,现假设每种xref组件(xref component)都专门负责一种类型数据的交叉引用更新。交叉引用更新程序(XRefUpdator)在被构造的时候,会通过反射列举出当前assembly中的所有components,以便在更新的时候,逐一调用这些components的相应方法,完成对所有数据的更新。

        很明显,为了强化类型和扩展方便,我们会定义一个xref component的泛型类,泛型类型就是交叉引用数据(XRefData)。由此,出现如下定义:

    public interface IXRefData          
    {         
        // TODO: add definition here         
    }         
    
    public class XRefComponent<TData>         
        where TData : IXRefData         
    {         
        public void Update() { }        
    }         
    
    public class XRefPickData : IXRefData { }       
    
    public class XRefPackData : IXRefData { }
    
    

    好了,现在考察XRefUpdator的定义。根据上面的设计思路,XRefUpdator需要包含一个xref component的列表,以便在需要的时候进行遍历从而逐一更新数据:

    public class XRefUpdator   
    {   
        private List<XRefComponent<......   
    }  
    
     

        OK,到这里就傻眼了,上面的省略号部分不知道该怎么写,到底是XRefComponent<XRefPickData>还是XRefComponent<XRefPackData>,事实上两者都不是。由此引出了一个非常明显但又容易忽视的概念:泛型表达的是一组完全不同的类型。既然是不同的类型,我们也不可能将它们统一地装入一个列表当中。

        如何解决这样的问题?其实方法很简单,就是引入接口。废话不说了,看完下面的代码后,您就会豁然开朗:

    public interface IXRefData             
    {            
        // TODO: add definition here            
    }    
    
    public interface IXRefComponent   
    {   
        void Update();   
    }           
    
    public class XRefComponent<TData> : IXRefComponent   
        where TData : IXRefData            
    {            
        public void Update() { }            
    }            
    
    public class XRefPickData : IXRefData { }          
    
    public class XRefPackData : IXRefData { }         
    
    public class XRefUpdator   
    {   
      private List<IXRefComponent> components = new List<IXRefComponent>();   
    
      public XRefUpdator   
      {   
        foreach(Type type in this.GetType().Assembly.GetExportedTypes())   
        {   
          if (typeof(IXRefComponent).IsAssignableFrom(type))   
          {   
            components.Add((IXRefComponent)Activator.CreateInstance(type));   
          }   
        }   
      }   
    }  
    
     

        到这里,我想您应该觉得事情已经结束了。事实上并非如此。如果XRefComponent<TData>类中的Update方法需要用到TData类型的参数,或者返回值是TData类型,那么,你就无法简单地使用IXRefComponent接口去做抽象,因为你没有办法在这个接口中定义Update方法。如果你使用泛型接口,那又到了问题的起点:你遇到的是一堆完全不同的接口。在后续的文章中,我会介绍如何解决这个问题。

  • 相关阅读:
    C#编程语言详解(第2版) 11.3 类和结构的区别
    .Net程序员如何快速成长之我见
    封装 JMail 4.4 的 POP3 为 .Net 组件 (.dll 程序集),实现 "邮件(附件) 到达" 等 "事件,c#接收邮件
    POJ1163The Triangle
    hdoj_1231&&hdoj_1003最大连续子序列
    数组名++操作导致的_BLOCK_TYPE_IS_VALID
    《windows程序设计》第二章学习心得
    error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup
    Windows环境下Unicode编程总结
    已知顺序表L递增有序,写一算法,将X插入到线性表的适当位置,以保持线性表的有序
  • 原文地址:https://www.cnblogs.com/daxnet/p/1686966.html
Copyright © 2020-2023  润新知