asp.net App_Code文件夹相关操作
最近用到了App_Code文件夹,想要实现动态编译文件的方式,即替换文件夹中的类文件从而达到实时修改代码的效果,类似web.config,网上查到的资料基本都是把文件夹中的类文件修改属性为"编译",这跟我想要的效果不一样,但是不这么做的话在VS中无法调用,想来想去只能使用反射+Expression+缓存的方式来实现了.
研究了几个小时后搞了一个App_Code帮助类
假设App_Code文件夹中有这么一个类
namespace WebTest.App_Code
{
public static class TestClass
{
public const string TestConst = "testConst"; public readonly static string TestStaticField = "testStaticField"; public static string TestStaticProperty { get { return "testStaticProperty"; } } public static string TestStaticMethod(string value)
{
return value;
} public static string TestStaticMethod(string value1, string value2)
{
return value1 + value2;
}
}
}
我想要获取以下内容:
1.常量TestConst的值
2.静态字段TestStaticField的值
3.静态属性TestStaticProperty的值
4.静态方法TestStaticMethod(string value)的调用结果
5.静态方法TestStaticMethod(string value1,string value2)的调用结果
好了,在VS中是无法直接使用的,因为类文件属性未修改为"编译",但是这个类会被动态编译成一个程序集.
App_Code生成的动态程序集可以通过 System.Web.Compilation.BuildManager.CodeAssemblies 拿到(PreApplicationStart阶段无法获取)
public static IEnumerable<Assembly> GetApp_CodeAssemblies()
{
if (BuildManager.CodeAssemblies != null)
{
foreach (object item in BuildManager.CodeAssemblies)
{
Assembly assembly;
try
{
assembly = (Assembly)item;
}
catch
{
continue;
}
yield return assembly;
}
} }
首先我们需要获取类型的Type对象,为了提高性能,代码中使用字典来缓存数据
static readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
static readonly ConcurrentDictionary<Tuple<Type, string>, object> _constMap = new ConcurrentDictionary<Tuple<Type, string>, object>();
static readonly ConcurrentDictionary<Tuple<Type, string>, Func<object>> _staticFieldFactoryMap = new ConcurrentDictionary<Tuple<Type, string>, Func<object>>();
static readonly ConcurrentDictionary<Tuple<Type, string>, Func<object>> _staticPropertyFactoryMap = new ConcurrentDictionary<Tuple<Type, string>, Func<object>>();
static readonly ConcurrentDictionary<Tuple<Type, string, string>, Delegate> _staticMethodFactoryMap = new ConcurrentDictionary<Tuple<Type, string, string>, Delegate>();
为了使用方便,扩展了微软的ConcurrentDictionary类
namespace System.Web
{
internal class ConcurrentDictionary<TKey, TValue> : System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
{
public TValue Get(TKey key, Func<TValue> factory)
{
TValue value;
if (!this.TryGetValue(key, out value))
{
value = factory();
this.TryAdd(key, value);
}
return value;
}
}
}
#region Types
public static Type[] GetTypes(string fullName)
{
return GetTypesInternal(fullName).ToArray();
} public static Type GetType(string fullName)
{
return _typeMap.Get(fullName, () => GetTypesInternal(fullName).FirstOrDefault());
} static IEnumerable<Type> GetTypesInternal(string fullName)
{
foreach (var assembly in Tools.GetApp_CodeAssemblies())
{
var type = assembly.GetTypes().FirstOrDefault(o => o.FullName == fullName);
if (type != null)
{
yield return type;
}
}
}
#endregion
好了,拿到类型了,按顺序解决上面的5个问题
1.常量值
/// <summary>
/// 获取常量值
/// </summary>
/// <param name="fullTypeName"></param>
/// <param name="constName"></param>
/// <returns></returns>
public static object GetConstValue(string fullTypeName, string constName)
{ var type = GetType(fullTypeName); if (type == null)
{
return null;
} return GetConstValue(type, constName);
}
/// <summary>
/// 获取常量值
/// </summary>
/// <param name="type"></param>
/// <param name="constName"></param>
/// <returns></returns>
public static object GetConstValue(Type type, string constName)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
return _constMap.Get(new Tuple<Type, string>(type, constName), () =>
{
var field = type.GetField(constName);
if (field == null)
{
return null;
}
if ((field.Attributes & System.Reflection.FieldAttributes.Literal) != )
{
return field.GetValue(null);
}
return null;
});
}
2.静态字段值
/// <summary>
/// 获取静态字段值
/// </summary>
/// <param name="fullTypeName"></param>
/// <param name="fieldName"></param>
/// <returns></returns>
public static object GetStaticFieldValue(string fullTypeName, string fieldName)
{ var type = GetType(fullTypeName); if (type == null)
{
return null;
} return GetStaticFieldValue(type, fieldName);
} /// <summary>
/// 获取静态字段值
/// </summary>
/// <param name="type"></param>
/// <param name="fieldName"></param>
/// <returns></returns>
public static object GetStaticFieldValue(Type type, string fieldName)
{
if (type == null)
{
throw new ArgumentNullException("type");
} var factory = _staticFieldFactoryMap.Get(new Tuple<Type, string>(type, fieldName), () =>
{
var field = type.GetField(fieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (field == null)
{
return null;
}
var fieldExpression = Expression.Field(null, field);
return Expression.Lambda<Func<object>>(fieldExpression).Compile(); }); return factory == null ? null : factory(); }
3.静态属性值
/// <summary>
/// 获取静态属性值
/// </summary>
/// <param name="fullTypeName"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static object GetStaticPropertyValue(string fullTypeName, string propertyName)
{ var type = GetType(fullTypeName); if (type == null)
{
return null;
} return GetStaticPropertyValue(type, propertyName);
}
/// <summary>
/// 获取静态属性值
/// </summary>
/// <param name="type"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static object GetStaticPropertyValue(Type type, string propertyName)
{
if (type == null)
{
throw new ArgumentNullException("type");
} var factory = _staticPropertyFactoryMap.Get(new Tuple<Type, string>(type, propertyName), () =>
{
var property = type.GetProperty(propertyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (property == null)
{
return null;
}
var propertyExpression = Expression.Property(null, property);
return Expression.Lambda<Func<object>>(propertyExpression).Compile(); }); return factory == null ? null : factory(); }
4,5.方法返回值
/// <summary>
/// 获取静态方法值
/// </summary>
/// <param name="fullTypeName"></param>
/// <param name="methodName"></param>
/// <param name="args"></param>
/// <returns></returns>
public static object GetStaticMethodValue(string fullTypeName, string methodName, params dynamic[] args)
{ var type = GetType(fullTypeName); if (type == null)
{
return null;
} return GetStaticMethodValue(type, methodName, args);
} /// <summary>
/// 获取静态方法值
/// </summary>
/// <param name="type"></param>
/// <param name="methodName"></param>
/// <param name="args"></param>
/// <returns></returns>
public static object GetStaticMethodValue(Type type, string methodName, params dynamic[] args)
{
if (type == null)
{
throw new ArgumentNullException("type");
} var types = args.Select(o => (Type)o.GetType()).ToArray(); string argKey = Tools.GetValueFromIEnumerable(types.Select(o => o.FullName)); dynamic factory = _staticMethodFactoryMap.Get(new Tuple<Type, string, string>(type, methodName, argKey), () =>
{
var method = type.GetMethod(methodName, types);
if (method == null)
{
return null;
}
if (method.ReturnType == null)
{
return null;
} var parameters = new ParameterExpression[args.Length];
for (int i = ; i < args.Length; i++)
{
parameters[i] = Expression.Parameter(args[i].GetType(), "args" + i);
}
var methodExpression = Expression.Call(null, method, parameters);
return Expression.Lambda(methodExpression, parameters).Compile();
}); if (factory == null)
{
return null;
} switch (args.Length)
{
case :
return factory();
case :
return factory(args[]);
case :
return factory(args[], args[]);
case :
return factory(args[], args[], args[]);
case :
return factory(args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
case :
return factory(args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[], args[]);
default:
throw new NotImplementedException("参数太多了...");
}
}
好了,做个测试:
public class TestController : Controller
{
// GET: Test
public ActionResult Index()
{ string testConst = App_CodeHelper.GetConstValue("WebTest.App_Code.TestClass", "TestConst") as string; string testStaticField = App_CodeHelper.GetStaticFieldValue("WebTest.App_Code.TestClass", "TestStaticField") as string; string testStaticProperty = App_CodeHelper.GetStaticPropertyValue("WebTest.App_Code.TestClass", "TestStaticProperty") as string; string testStaticMethod1 = App_CodeHelper.GetStaticMethodValue("WebTest.App_Code.TestClass", "TestStaticMethod", "我是value") as string; string testStaticMethod2 = App_CodeHelper.GetStaticMethodValue("WebTest.App_Code.TestClass", "TestStaticMethod", "我是value1", "我是value2") as string; return Json(new
{
testConst,
testStaticField,
testStaticProperty,
testStaticMethod1,
testStaticMethod2
}, JsonRequestBehavior.AllowGet);
}
}
得到结果:
{"testConst":"testConst","testStaticField":"testStaticField","testStaticProperty":"testStaticProperty","testStaticMethod1":"我是value","testStaticMethod2":"我是value1我是value2"}
现在我们用记事本打开TestClass类文件,修改代码保存
namespace WebTest.App_Code
{
public static class TestClass
{
public const string TestConst = "testConst1"; public readonly static string TestStaticField = "testStaticField1"; public static string TestStaticProperty { get { return "testStaticProperty1"; } } public static string TestStaticMethod(string value)
{
return value+"";
} public static string TestStaticMethod(string value1, string value2)
{
return value1 +"+"+ value2;
}
}
}
此时应用程序重启,再次访问,结果变成了:
{"testConst":"testConst1","testStaticField":"testStaticField1","testStaticProperty":"testStaticProperty1","testStaticMethod1":"我是value1","testStaticMethod2":"我是value1+我是value2"}
效果还是不错的,当然如果只是使用字段属性的话完全可以使用web.config,但是动态调用方法的话还是可以派上用场的!!!
asp.net App_Code文件夹相关操作的更多相关文章
- java文件夹相关操作 演示样例代码
java文件夹相关操作 演示样例代码 package org.rui.io; import java.io.File; import java.io.FilenameFilter; import ja ...
- Java IO_001.File类--文件或文件夹相关操作
Java IO之File对象常用操作 File类:用于文件或文件夹或网址相关联的操作.可以关联或不关联文件(即关联不存在的文件).构造函数有: public File(String pathname) ...
- asp.net自己创建的app_code文件夹中的类不能访问的解决办法
在Web应用程序中不能通过右键项目-〉”添加“-〉”添加ASP.NET文件夹“方式添加 .因为Web应用程序中App_Code就不存在 .不过可以通过手动的方式创建,添加一个文件夹命名为App_Cod ...
- Asp.net WebForm 中无法引用App_Code文件夹下的类
在VS2013中新建asp.net webform应用程序,手动添加"APP_Code"文件夹并新建类文件,发现这些类无法在APP_Code文件夹以外被引用. 解决办法: 选中类文 ...
- ASP.NET Web网站中App_Code文件夹的作用及使用场景
原文地址:Web Site项目和ASP.NET Web Application中App_Code文件夹的作用作者:宾的宾 我现在要建一个ASP.NET的网站了,不难吧,开始动手.如下图: 这种方法建立 ...
- Asp.net对文件夹和文件的操作类
using System; using System.IO; using System.Web; namespace SEC { /**//// /// 对文件和文件夹的操作类 /// public ...
- webform工程中aspx页面为何不能调用appcode文件夹下的类(ASP.NET特殊文件夹的用法)
App_code 只有website类型的工程才有效. App_Code 下创建的.cs文件仅仅是“内容”不是代码.你设置那个文件为“编译”就行了. 其他特殊文件夹 1. Bin文件夹 Bin文件夹包 ...
- python之文件的读写和文件目录以及文件夹的操作实现代码
这篇文章主要介绍了python之文件的读写和文件目录以及文件夹的操作实现代码,需要的朋友可以参考下 为了安全起见,最好还是给打开的文件对象指定一个名字,这样在完成操作之后可以迅速关闭文件,防止一些无用 ...
- Apex 中文件夹相关的单元测试
Salesforce 中的文件夹 在 Salesforce 中,我们可以建立各种文档.报表.仪表板.电子邮件模板等.它们都被保存在相应的文件夹中. Salesforce 的后端将这些文件夹保存为 Fo ...
随机推荐
- 关于FluentNhibernate数据库连接配置,请教
在用FluentNHibernate映射数据库,出现这个问题,一天多了也没解决,求各位大神支招 问题是与map对应的表已成功创建,出错的地方是最后的 .BuildSessionFactory(); ...
- 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...
- 人人都是 DBA(XIV)存储过程信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- Nim教程【六】
目前看来这是国内第一个关于Nim的系列教程 先说废话 Rust1.0已经发布了, 国内有一个人为这个事情写了一篇非常长的博客, 这篇文章我前几天草草的看了一下,只记得这位朋友追Rust的艰辛,其他内容 ...
- SVM-线性可分支持向量机
SVM-线性可分支持向量机 如果您想体验更好的阅读:请戳这里littlefish.top 函数间隔和几何间隔 给定线性可分训练数据集,通过间隔最大化或等价地求解相应的凸二次规划问题学习得到的分离超平面 ...
- MySQL 5.7新特性之Generated Column(函数索引)
MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...
- Java-异常处理练习
1.建立exception包,编写TestException.java程序,主方法中有以下代码,确定其中可能出现的异常,进行捕获处理. package Yichang; public class Te ...
- MVVM架构~Knockoutjs系列之对象与对象组合
返回目录 在面向对象的程序设计里,对象是核心,一切皆为对象,对象与对象之间的关系可以表现为继承和组合,而在Knockoutjs或者JS里,也存在着对象的概念,今天主要说一下JS里的对象及对象的组合. ...
- EF架构~为EF DbContext生成的实体添加注释(T5模板应用)
回到目录 相关文章系列 第八回 EF架构~将数据库注释添加导入到模型实体类中 第二十一回 EF架构~为EF DbContext生成的实体添加注释(T4模板应用) 第二十二回EF架构~为EF DbCo ...
- 谷歌大牛 Rob Pike 的 5 个编程原则
谷歌大牛 Rob Pike 的 5 个编程原则 简介: Rob Pike,目前谷歌公司最著名的软件工程师之一,曾是贝尔实验室Unix开发团队成员,Plan9操作系统开发的主要领导人,Inferno操作 ...