在这一点上我们必须做出一些妥协。首先,运行时异常时几乎不可避免的。我能想到的唯一方法是制作一个自定义插件加入到 Visual Studio 中那将会抛出额外的编译错误。那为了这篇文章的目的,就必须处理这个运行时异常。然而最大的问题是我们还是要为我们需要支持的每一个给类型写一个函数。一定会有解决这个问题的办法!
代码这是我目前的一个通用的数学模式的版本:
using Microsoft.CSharp; using System;
using System.CodeDom.Compiler;
using System.Reflection;
namespace RuntimeCodeCompiling {
public static class Program
{
public static Action action;
public static void Main(string[] args)
{
Console.WriteLine("Sum(double): " + Generic_Math<double>.Sum(new double[] { 1, 2, 3, 4, 5 }));
Console.WriteLine("Sum(int): " + Generic_Math<int>.Sum(new int[] { 1, 2, 3, 4, 5 }));
Console.WriteLine("Sum(decimal): " + Generic_Math<decimal>.Sum(new decimal[] { 1, 2, 3, 4, 5 }));
Console.ReadLine();
}
#region Generic Math Library Example
public static class Generic_Math<T>
{
public static Func<T[], T> Sum = (T[] array) =>
{ // This implementation will make this string be stored in memory during runtime,
//so it might be better to read it from a file
string code = "(System.Func<NUMBER[], NUMBER>)((NUMBER[] array) =>
{ NUMBER sum = 0; for (int i = 0; i < array.Length; i++) sum += array[i]; return sum; })";
// This requires that "T" has an implicit converter from int values and a "+" operator
code = code.Replace("NUMBER", typeof(T).ToString());
// This small of an example requires no namspaces or references
Generic_Math<T>.Sum = Generate.Object<Func<T[], T>>(new string[] { }, new string[] { }, code);
return Generic_Math<T>.Sum(array);
};
}
/// <summary>Generates objects at runtime.</summary>
internal static class Generate
{
/// <summary>Generates a generic object at runtime.</summary>
/// <typeparam>The type of the generic object to create.</typeparam>
/// <param>The required assembly references.</param>
/// <param>The required namespaces.</param>
/// <param>The object to generate.</param>
/// <returns>The generated object.</returns>
internal static T Object<T>(string[] references, string[] name_spaces, string code)
{
string full_code = string.Empty;
if (name_spaces != null)
for (int i = 0; i < name_spaces.Length; i++)
full_code += "using " + name_spaces[i] + ";";
full_code += "namespace Seven.Generated
{";
full_code += "public class Generator
{";
full_code += "public static object Generate()
{ return " + code + "; } } }";
CompilerParameters parameters = new CompilerParameters();
foreach (string reference in references)
parameters.ReferencedAssemblies.Add(reference);
parameters.GenerateInMemory = true;
CompilerResults results = new CSharpCodeProvider().CompileAssemblyFromSource(parameters, full_code);
if (results.Errors.HasErrors)
{
string error = string.Empty;
foreach (CompilerError compiler_error in results.Errors)
error += compiler_error.ErrorText.ToString() + "\n";
throw new Exception(error);
}
MethodInfo generate = results.CompiledAssembly.GetType("Seven.Generated.Generator").GetMethod("Generate");
return (T)generate.Invoke(null, null);
}
}
#endregion
} }
代码工作原理: