前言
反射使用,让我们的程序可以动态增加一些功能,让原本固化的步骤逻辑变得动态,这是它的优点。当然使用反射首次加载会有性能损耗以及使用复杂;但是现在大家都在讲动态,使用好它应该是一个重要的编程理念提升。MVC、ORM、IOC、AOPA都有使用这个东西了。如果要考虑性能,可以考虑缓存程序集,我们保证程序只加载一次就好。
一、直接利用反射读写对象的值
static void Main(string[] args)
{
Person p = new Person() { Name = "丁竹", Age = 26, Sex = true };
p.Working("readinof");
//利用反射读取值
object obj = p;
var type = obj.GetType();
foreach (var item in type.GetProperties())
{
string value = item.GetValue(obj, null).ToString();
Console.WriteLine($"{item.Name} {value}");
}
Assembly ass = Assembly.Load("ReadInfo");
object pObj = ass.CreateInstance("ReadInfo.Person");
//利用反射设置值
{
System.Reflection.PropertyInfo propertyInfo = type.GetProperty("Name");
propertyInfo.SetValue(obj, "ding", null);
}
Console.Read();
}
二、通过反射调用实例
static void Main(string[] args)
{
//[1].CsharpCodePrivode
//提供对C#代码生成器和代码编译器的实例的访问。如果要动态生成VB代码,可以使用VBCodeProvider.
//CreateCompiler():获取编译器的实例
CSharpCodeProvider objcsharpcodeprivoder = new CSharpCodeProvider();
//[2].ICodeComplier
//定义用于调用源代码编译的接口或使用指定编译器的CodeDOM树。
//每种编译方法都接受编译器的ComplierParameter对象,并返回指示编译结果的CompilerResults对象
ICodeCompiler codeCompiler = objcsharpcodeprivoder.CreateCompiler();
//[3].ComplierParameters 表示用于调用编译器的参数
//ReferencedAssembies:获取当前项目所引用的程序集。Add方法为程序集添加引用
//GenerateExecutable:获取或设置一个值,该值指示是否生成可执行文件。若此属性为false,则生成Dll,默认是false.
//GenerateInMemor:获取或设置一个值,该值指示是否在内存中生成输出。
CompilerParameters objcompilerparameters = new CompilerParameters();
// objcompilerparameters.ReferencedAssemblies.Add("System.dll");
objcompilerparameters.GenerateExecutable = false;
objcompilerparameters.GenerateInMemory = true;
//[4].CompilerResults 表示从编译器返回的编译结果
//CompiedAssembly:获取或设置以编译的程序集,Assembly类型。
CompilerResults cr = codeCompiler.CompileAssemblyFromSource(objcompilerparameters, GenerateCode());
if (cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach (CompilerError item in cr.Errors)
{
Console.WriteLine(item.ErrorText);
}
}
else
{
//通过反馈,调用HelloWorld实例
Assembly assembly = cr.CompiledAssembly;
object objHelloWorld = assembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
Console.WriteLine(objMI.Invoke(objHelloWorld,null));
}
Console.ReadLine();
}
static string GenerateCode()
{
StringBuilder sb = new StringBuilder();
sb.Append("using System;");
sb.Append(Environment.NewLine);
sb.Append("namespace DynamicCodeGenerate");
sb.Append(Environment.NewLine);
sb.Append("{");
sb.Append(Environment.NewLine);
sb.Append(" public class HelloWorld");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.Append(" public string OutPut()");
sb.Append(Environment.NewLine);
sb.Append(" {");
sb.Append(Environment.NewLine);
sb.Append(" return \"Hello world!\";");
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
sb.Append(" }");
sb.Append(Environment.NewLine);
sb.Append(" }");
string code = sb.ToString();
Console.WriteLine(code);
Console.WriteLine();
return code;
}
三、通过动态加载Dll生成实例
dom.DoCompileFile(Path.Combine(pathStr, filename), "Test.dll");
MySampleDomain = AppDomain.CreateDomain("MySampleDomain");
ass = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "Test.dll");
obj = MySampleDomain.CreateInstanceAndUnwrap(ass.FullName, "Sample.Demo");
四、通过反射调用方法
Type type = obj.GetType();
MethodInfo method = type.GetMethod("Add");
int a=Convert.ToInt32( method.Invoke(obj, new object[] { 1,3 }));
Console.WriteLine(a);
五、完整代码
public class ReflexHelp
{
public void Execute(string gencode)
{
//[1].CsharpCodePrivode
//提供对C#代码生成器和代码编译器的实例的访问。如果要动态生成VB代码,可以使用VBCodeProvider.
//CreateCompiler():获取编译器的实例
CSharpCodeProvider objcsharpcodeprivoder = new CSharpCodeProvider();
//[2].ICodeComplier
//定义用于调用源代码编译的接口或使用指定编译器的CodeDOM树。
//每种编译方法都接受编译器的ComplierParameter对象,并返回指示编译结果的CompilerResults对象
ICodeCompiler codeCompiler = objcsharpcodeprivoder.CreateCompiler();
//[3].ComplierParameters 表示用于调用编译器的参数
//ReferencedAssembies:获取当前项目所引用的程序集。Add方法为程序集添加引用
//GenerateExecutable:获取或设置一个值,该值指示是否生成可执行文件。若此属性为false,则生成Dll,默认是false.
//GenerateInMemor:获取或设置一个值,该值指示是否在内存中生成输出。
CompilerParameters objcompilerparameters = new CompilerParameters();
// objcompilerparameters.ReferencedAssemblies.Add("System.dll");
objcompilerparameters.GenerateExecutable = false;
objcompilerparameters.GenerateInMemory = true;
//[4].CompilerResults 表示从编译器返回的编译结果
//CompiedAssembly:获取或设置以编译的程序集,Assembly类型。
CompilerResults cr = codeCompiler.CompileAssemblyFromSource(objcompilerparameters, gencode);
if (cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach (CompilerError item in cr.Errors)
{
Console.WriteLine(item.ErrorText);
}
}
else
{
//通过反馈,调用HelloWorld实例
Assembly assembly = cr.CompiledAssembly;
object objHelloWorld = assembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
Console.WriteLine(objMI.Invoke(objHelloWorld, null));
}
}
public object GenObject(string dllFileName, string typeName)
{
Assembly ass = Assembly.LoadFile(dllFileName);
return ass.CreateInstance(typeName);
}
public int GetAddInfo(object obj, string methrName)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methrName);
return Convert.ToInt32(method.Invoke(obj, new object[] { 1, 3 }));
}
/// <summary>
/// 编译代码
/// </summary>
/// <param name="provider">编译器</param>
/// <param name="sourceFile">源文件</param>
/// <param name="gentenFile">生成文件名</param>
/// <returns>编译结果</returns>
public CompilerResults CompileCode(CodeDomProvider provider, string sourceFile, string gentenFile)
{
string[] referenceAssemblies = { "System.dll" };
CompilerParameters cp = new CompilerParameters(referenceAssemblies, gentenFile, false);
cp.GenerateExecutable = false;//设置是否要包含一个入口点
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
return cr;
}
}