C#学习之反射机制及应用场景2
前言:
以前我是做物流码追溯系统的,主要是对原辅料喷码,采集,出库,追踪等操作,而我只负责其中一小块部分,主要是对线下所有的手持设备提供扫描接口。为了针对所有不同的项目提供一个标准的接口,我采用一些设计模式和反射,今天我就主要说一下我如何利用反射将扫码接口进行统一标准化。
场景如下:
现在存在多个项目每个项目共同点就是参数一样,返回参数统一ServiceResult 进行反序列化,当调用扫码接口的时候,由配置界面配置的具体调用者程序集文件全路径决定。这样就实现不管多少项目都可以很灵活的更改配置界面文件路径来实现具体调用扫码接口。
代码如下
1: 定义抽象的命令接受者类
public abstract class Receiver { public Receiver() { } public abstract void ScanCode(string codeId, ServiceResult result); }
2:定义抽象的扫码命令类
public abstract class Command { protected Receiver _receiver; public Command(Receiver receiver) { this._receiver = receiver; } public abstract void ScanCode(string codeId, ServiceResult result); }
3: 定义调用者 构建函数传递真正执行调用者
public class Invoke { public Command command; public Invoke(Command command) { this.command = command; } public void ExecuteCommand(string codeId, ServiceResult result) { command.ScanCode(codeId,result); } }
3: 返回标准实体
public class ServiceResult { public bool Succeed { set; get; } /// <summary> /// 是错误 /// </summary> public string ErrorCode { set; get; } /// <summary> /// 错误或警告消息 /// </summary> public string Message { set; get; } }
4:Db调用者继承上面抽象接收者
public class DbReceiver : Receiver { public override void ScanCode(string codeId, ServiceResult result) { //做一些业务逻辑操作 result.Message = string.Format("调用的扫码对象:{0},扫描的码:{1}", "Db", codeId); result.Succeed = true; } }
5: Db 具体执行得扫码命令
public class DbCodeCommand: Command { public DbCodeCommand(Receiver receiver) : base(receiver) { } public override void ScanCode(string codeId, ServiceResult result) { _receiver.ScanCode(codeId, result); } }
6: Dz调用者继承上面抽象接收者
public class DzReceiver : Receiver { public override void ScanCode(string codeId, ServiceResult result) { //做一些业务逻辑操作 result.Message = string.Format("调用的扫码对象:{0},扫描的码:{1}", "Dz", codeId); result.Succeed = true; } }
6:Dz具体执行得扫码命令
public class DzScanCodeCommand: Command { public DzScanCodeCommand(Receiver receiver) : base(receiver) { } public override void ScanCode(string codeId, ServiceResult result) { _receiver.ScanCode(codeId, result); } }
6: 通过反射定义接收者工厂
public static class ReceiverFactory { private static Receiver receiver; private static readonly object initObj = new object(); public static Receiver CreateInstance(string assemblyFile) { if (receiver == null) { lock (initObj) { if (receiver == null) { if (assemblyFile == null || string.IsNullOrEmpty(assemblyFile)) return null; Assembly ass = Assembly.LoadFrom(assemblyFile); foreach (Type typ in ass.GetTypes()) { if (!typ.IsAbstract && typ.IsSubclassOf(typeof(Receiver))) { receiver = (Receiver)Activator.CreateInstance(typ); break; } } } } } return receiver; } }
7: 通过反射定义命令者工厂
public static class CommandFactory { private static Command command; private static readonly object initObj = new object(); public static Command CreateInstance(string assemblyFile, Receiver receiver) { if (command == null) { lock (initObj) { if (command == null) { if (assemblyFile == null || string.IsNullOrEmpty(assemblyFile)) return null; Assembly ass = Assembly.LoadFrom(assemblyFile); foreach (Type typ in ass.GetTypes()) { if (!typ.IsAbstract && typ.IsSubclassOf(typeof(Command))) { command = (Command)Activator.CreateInstance(typ,new object[] { receiver }); break; } } } } } return command; } }
7:标准扫码接口
[HttpPost] public string OutPutCode() { ServiceResult serviceResult = new ServiceResult(); StreamReader reader = new StreamReader(HttpContext.Request.InputStream); string postData = reader.ReadToEnd(); if (postData == null || string.IsNullOrEmpty(postData)) return string.Empty; var dyModel = JsonConvert.DeserializeObject<dynamic>(postData); Receiver receiver = ReceiverFactory.CreateInstance(@"程序集执行的全路径");
Command commmand = CommandFactory.CreateInstance(@"程序集执行的全路径", receiver); Invoke invoke = new Invoke(commmand); string codeId = dyModel.codeId; invoke.ExecuteCommand(codeId, serviceResult); return JsonConvert.SerializeObject(serviceResult); }
上面ReceiverFactory,CreateInstance("程序集路径") 可以直接写到数据库配置表里,通过配置界面上传不同的程序集文件决定具体执行Dz,还是Db 扫码接口。

浙公网安备 33010602011771号