zoukankan      html  css  js  c++  java
  • Work.Dynamic.Loaddll.Note

    今天做动态加载dll发现一个好的泛型读取列的方法,结合自己的使用,还有自己的命名的越来越感觉好一些,看代码就像读英文。

    DllFile.cs.Code
     1     /// <summary>
     2     /// dll文件
     3     /// </summary>
     4     internal struct DllFile
     5     {
     6         /// <summary>
     7         /// 文件名
     8         /// </summary>
     9         public string Name { get; set; }
    10 
    11         /// <summary>
    12         /// 二进制文件
    13         /// </summary>
    14         public byte[] Content { get; set; }
    15 
    16         /// <summary>
    17         /// 描述
    18         /// </summary>
    19         public string Comment { get; set; }
    20 
    21         /// <summary>
    22         /// 上传用户id
    23         /// </summary>
    24         public string OwnerId { get; set; }
    25 
    26         /// <summary>
    27         /// 上传时间
    28         /// </summary>
    29         public DateTime UploadTime { get; set; }
    30     }
    DataRow.ReadColumn.Code.Generic (泛型读取列.感觉还不错)
     1       private static T GetColumnValue<T>(DataRow dr, string name)
     2         {
     3             try
     4             {
     5                 if (dr[name] == DBNull.Value)
     6                 {
     7                     return GetDefault<T>();
     8                 }
     9                 else
    10                 {
    11                     return (T)dr[name];
    12                 }
    13             }//如果不存在这一列
    14             catch (ArgumentException ex)
    15             {
    16                 throw new ArgumentException(string.Format("{0}列不存在。", name));
    17             }
    18         }
    19         private const string emptyStr = "";
    20         /// <summary>
    21         /// 根据类型获取默认值
    22         /// </summary>
    23         /// <typeparam name="T"></typeparam>
    24         /// <returns></returns>
    25         private static T GetDefault<T>()
    26         {
    27             T t = default(T);
    28             if (emptyStr is T)
    29                 return (T)(object)emptyStr;
    30             return t;
    31         }

    结合自己的代码读取列

    Read.DllFile from DataRow.Code
     1   protected ICollection<DllFile> GetDllFiles(DataSet ds)
     2         {
     3             ICollection<DllFile> result = new Collection<DllFile>();
     4             if (null == ds)
     5                 throw new ArgumentNullException("ds");
     6             int rCount = ds.Tables[0].Rows.Count;
     7             if (rCount > 0)
     8             {
     9                 for (int i = 0; i < rCount; i++)
    10                 {
    11                     DataRow dr = ds.Tables[0].Rows[i];
    12                     result.Add(FormatDllFile(dr));
    13                 }
    14             }
    15             return result;
    16         }
    17 
    18         private DllFile FormatDllFile(DataRow dr)
    19         {
    20             DllFile file = new DllFile();
    21             file.OwnerId = GetColumnValue<string>(dr, userField);
    22             file.Name = GetColumnValue<string>(dr, fileNameField);
    23             file.Content = GetColumnValue<byte[]>(dr, fileContentField);
    24             file.Comment = GetColumnValue<string>(dr, commentField);
    25             file.UploadTime = GetColumnValue<DateTime>(dr, updateTimeField);
    26             return file;
    27         }
    28         /// <summary>
    29         /// 根据类型或DataRow列
    30         /// </summary>
    31         /// <typeparam name="T"></typeparam>
    32         /// <param name="dr"></param>
    33         /// <param name="name"></param>
    34         /// <returns></returns>
    35         private static T GetColumnValue<T>(DataRow dr, string name)
    36         {
    37             try
    38             {
    39                 if (dr[name] == DBNull.Value)
    40                 {
    41                     return GetDefault<T>();
    42                 }
    43                 else
    44                 {
    45                     return (T)dr[name];
    46                 }
    47             }//如果不存在这一列
    48             catch (ArgumentException ex)
    49             {
    50                 throw new ArgumentException(string.Format("{0}列不存在。", name));
    51             }
    52         }
    53         private const string emptyStr = "";
    54         /// <summary>
    55         /// 根据类型获取默认值
    56         /// </summary>
    57         /// <typeparam name="T"></typeparam>
    58         /// <returns></returns>
    59         private static T GetDefault<T>()
    60         {
    61             T t = default(T);
    62             if (emptyStr is T)
    63                 return (T)(object)emptyStr;
    64             return t;
    65         }

    设计通过接口和反射来实现程序模块之间的解耦关系的一种机制,实现者将接口的实现类的Type和标记注册的程序集中,程序启动,或者用户更换dll到数据库时,更新全局静态注册字典,将类型更新到字典中。

    使用者根据与实现者沟通好的标记,创建接口实例,最终可以在不同的模块调用接口方法。

    程序集属性类

    Assembly.ExtensionAttribute.Code
     1     public class RegisterImplAttribute : Attribute
     2     {
     3         public Type InterfaceType { get; private set; }
     4 
     5         public string ImplFlag { get; private set; }
     6 
     7         public Type ImplType { get; private set; }
     8 
     9         public RegisterImplAttribute(Type implType, string implFlag)
    10         {
    11             this.ImplType = implType;
    12             this.ImplFlag = implFlag;
    13         }
    14 
    15         public RegisterImplAttribute(Type iType, Type implType, string implFlag)
    16         {
    17             this.InterfaceType = iType;
    18             this.ImplType = implType;
    19             this.ImplFlag = implFlag;
    20         }
    21     }

    重要的一步在程序集中添加接口实现类和实现类的标记,打开工程下.Properties/Assemboy.cs

    1 在文件中添加程序集属性。
    2 [assembly: Dynamic.RegisterImpl(typeof(AppendixFileController), "CRCC.Appendixs.1")]
    3 "CRCC.Appendixs.1"是接口实现类的标记,用于与其他接口实现类区分。通过这个标记最终才能找到实现类的。

    设计一个静态服务类,用于保存dll,同时动态加载程序集和程序集中的接口实现类,最终提供给用于一个接口实例。

    DynamicDllService.Code
      1  public static class DynamicDllService
      2     {
      3         private static IDictionary<string, Type> IInstances = new Dictionary<string, Type>();
      4         /// <summary>
      5         /// 动态dll存放目录
      6         /// </summary>
      7         private static readonly string folderDir = System.AppDomain.CurrentDomain.BaseDirectory + "\\DyBin";
      8 
      9         /// <summary>
     10         /// 加载所有动态dll表中的dll、并注册
     11         /// </summary>
     12         public static void InitAllInstance(IContext context)
     13         {
     14             DynamicDllDao dllDao = new DynamicDllDao(context);
     15             ICollection<DllFile> files = dllDao.SelectAll();
     16             if (null != files && files.Count > 0)
     17             {
     18                 DllStreamLocalize dllReader = new DllStreamLocalize();
     19                 foreach (var file in files)
     20                 {
     21                     dllReader.SaveFileToLocal(file.Content, folderDir, file.Name);
     22                     string filePath = string.Format("{0}{1}", dllReader.VerifyPath(folderDir), dllReader.GetDllFullName(file.Name));
     23                     RegisterDllImpl(filePath);
     24                 }
     25             }
     26         }
     27 
     28         /// <summary>
     29         /// 保存dll并注册到系统中
     30         /// </summary>
     31         /// <param name="context">上下文</param>
     32         /// <param name="userId">用户id</param>
     33         /// <param name="fileName">文件名</param>
     34         /// <param name="filebit">二进制文件</param>
     35         /// <param name="comment">文件描述</param>
     36         public static void SaveFile(IContext context, string userId, string fileName, byte[] filebit, string comment)
     37         {
     38             if (null == context)
     39                 throw new ArgumentNullException("context");
     40             if (string.IsNullOrEmpty(fileName))
     41                 throw new ArgumentNullException("fileName");
     42             if (string.IsNullOrEmpty(userId))
     43                 throw new ArgumentNullException("userId");
     44             DynamicDllDao dllDao = new DynamicDllDao(context);
     45             DllFile? file = dllDao.SearchByFileName(fileName);
     46             if (file != null)
     47                 dllDao.Update(userId, fileName, filebit, comment);
     48             else
     49                 dllDao.Insert(userId, fileName, filebit, comment);
     50 
     51             //实例化到本地
     52             DllStreamLocalize dllReader = new DllStreamLocalize();
     53             dllReader.SaveFileToLocal(filebit, folderDir, fileName);
     54             string filePath = string.Format("{0}{1}", dllReader.VerifyPath(folderDir), dllReader.GetDllFullName(fileName));
     55             RegisterDllImpl(filePath);
     56         }
     57 
     58         private static void RegisterDllImpl(string filePath)
     59         {
     60             object o = new object();
     61             lock (o)
     62             {
     63                 IDictionary<string, Type> implTypes = GetInstanceTypes(filePath);
     64                 foreach (var item in implTypes)
     65                 {
     66                     if (IInstances.ContainsKey(item.Key))
     67                         IInstances[item.Key] = item.Value;
     68                     else
     69                         IInstances.Add(item);
     70                 }
     71             }
     72         }
     73 
     74         private static IDictionary<string, Type> GetInstanceTypes(string filePath)
     75         {
     76             if (string.IsNullOrEmpty(filePath))
     77                 throw new ArgumentNullException("filePath");
     78 
     79             if (!File.Exists(filePath))
     80                 throw new FileNotFoundException(string.Format("加载:{0},失败。", filePath));
     81             Assembly assmbly = Assembly.LoadFile(filePath);
     82             object[] assAttrs = assmbly.GetCustomAttributes(typeof(RegisterImplAttribute), false);
     83 
     84             IDictionary<string, Type> result = new Dictionary<string, Type>();
     85             if (assAttrs.Length > 0)
     86             {
     87                 for (int i = 0; i < assAttrs.Length; i++)
     88                 {
     89                     RegisterImplAttribute reg = assAttrs[i] as RegisterImplAttribute;
     90                     if (result.ContainsKey(reg.ImplFlag))
     91                         result[reg.ImplFlag] = reg.ImplType;
     92                     else
     93                         result.Add(reg.ImplFlag, reg.ImplType);
     94                 }
     95             }
     96             return result;
     97         }
     98 
     99         /// <summary>
    100         /// 根据接口实现标记获取,当前泛型接口实例
    101         /// </summary>
    102         /// <typeparam name="T">传入的泛型接口</typeparam>
    103         /// <param name="implFlag">接口实现类实现标记</param>
    104         /// <param name="initArgType">构造函数参数类型数组</param>
    105         /// <param name="initArgVal">构造函数参数值数组</param>
    106         /// <returns>接口实例</returns>
    107         public static T GetInterfaceImpl<T>(string implFlag, Type[] initArgType, object[] initArgVal)
    108         {
    109             T instance = default(T);
    110             Type implType;
    111             if (IInstances.TryGetValue(implFlag, out implType))
    112             {
    113                 try
    114                 {
    115                     ConstructorInfo construct = implType.GetConstructor(initArgType);
    116                     if (construct != null)
    117                         instance = (T)construct.Invoke(initArgVal);
    118                 }
    119                 catch (ArgumentException e)
    120                 {
    121                     throw new ArgumentException("反射生成实例失败,清检查构造函数参数信息。");
    122                 }
    123             }
    124             return instance;
    125         }
    126 
    127         /// <summary>
    128         /// 根据接口实例标记,获取接口实现,无构造函数参数
    129         /// </summary>
    130         /// <typeparam name="T">泛型接口</typeparam>
    131         /// <param name="implFlag">实现标记</param>
    132         /// <returns>接口实例</returns>
    133         public static T GetInterfaceImpl<T>(string implFlag)
    134         {
    135             T instance = default(T);
    136             Type implType;
    137             if (IInstances.TryGetValue(implFlag, out implType))
    138             {
    139                 try
    140                 {
    141                     instance = (T)System.Activator.CreateInstance(implType);
    142                 }
    143                 catch (ArgumentException e)
    144                 {
    145                     throw new ArgumentException("反射创建实例失败,请核实参数类型是否正确。");
    146                 }
    147             }
    148             return instance;
    149         }
    150     }

    DynamicDllService有三个公开方法,

    InitAllInstance:用于在程序启动时,将所有数据中的dll加InitAllInstance中。

    SaveFile:是保存dlll并同时动态加载dll中接口实现类和标记,这里注册到该类的静态私有字典(IInstances)中

    static T GetInterfaceImpl<T>(string implFlag):最终通过翻新方法返回泛型实例接口,T为所需要到的泛型接口,implFlag:实现类标记。

  • 相关阅读:
    php 调试
    php 格式
    php 函数 将数组转换成标量变量:extract()
    jQuery 方法
    php echo字符串的连接格式
    wampserver php 设置时间
    TableView使用CATransform3D特效动画
    苹果手机制作gif图片
    全局修改Lable/Button字体
    关于 presentViewController 时机
  • 原文地址:https://www.cnblogs.com/lovey/p/2994184.html
Copyright © 2011-2022 走看看