clr via c# 程序集加载和反射集(一)
1,程序集加载---弱的程序集可以加载强签名的程序集,但是不可相反.否则引用会报错!(但是,反射是没问题的)
//获取当前类的Assembly
Assembly.GetEntryAssembly()
//通过Load方法加载程序集
Assembly.Load
//通过LoadFrom加载指定路径名的程序集--可以时url对象.
Assembly LoadFrom(string path)
//只是反射,并确保程序集中的数据不被执行.
ReflectionOnlyLoadFrom()
ReflectionOnlyLoad(string assembly string)
2,发现程序集中定义的类型
class ReflectionRef
{
public static void Demo1()
{
string AssemblyName = "s7.net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693, processorArchitecture=MSIL";
Assembly a = Assembly.Load(AssemblyName);
Display(0, "{0}'s types:",a.FullName);
a.ExportedTypes.ToList().ForEach(x => Display(2, "t's FullName is {0}", x.FullName));
Console.WriteLine();
a = Assembly.GetEntryAssembly();
Display(0, "{0}'s types:", a.FullName);
a.ExportedTypes.ToList().ForEach(x => Display(2, "t's FullName is {0}", x.FullName)); }
private static void Display(int indent,string Format,params object[] obj)
{
Console.Write(new string(' ', indent * 2));
Console.WriteLine(Format, obj);
} }
结果:
s7.net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693's types:
t's FullName is S7.Net.TcpClientMixins
t's FullName is S7.Net.Conversion
2,类型对象的准确含义.
//通过实列获得类型
obj.GetType();
//通过Type类的静态函数GetType()
public static Type GetType (string typeName);//必须是FullName
//是否抛出异常和忽略大小写.
public static Type GetType (string typeName, bool throwOnError, bool ignoreCase);
//
参数
- typeName
- String
要获取的类型的程序集限定名称。 请参阅 AssemblyQualifiedName。 如果该类型位于当前正在执行的程序集中或者 Mscorlib.dll 中,则提供由命名空间限定的类型名称就足够了。
System.TypeInfo提供了实列成员DeclaredNestedTypes和GetDeclaredNestedType定义了类中嵌套的类型.
System.Reflection.Assembly 类型提供了实列成员
GetType \\string,输入的类型的全名
DefinedTypes \\ 返回所有定义的类型的TypeInfo.
public virtual System.Collections.Generic.IEnumerable<System.Reflection.TypeInfo> DefinedTypes { get; }
ExportedTypes\\返回所有定义的公共类型
public virtual System.Collections.Generic.IEnumerable<Type> ExportedTypes { get; }
type对象是轻量级引用,需要更多的了解类型本身,必须获取一个TypeInfo对象
TypeInfo ti = typeof(ReflectionRef).GetTypeInfo();
- IsPublic
- IsSealed
- IsAbstract
- IsClass
- IsValueType
- 另一些参数返回:
- Assembly
- AssemblyQulifiedName
- FullName
- Module
3,通过反射构建派生类的层次结构
- 批量加载程序集---注意,加载程序集的四个要素
{Name{0},PublicKeyToken={1},version={2},Culture={3}}
private static void LoadAssemblies()
{
String[] assemblies =
{
"System, PublicKeyToken={0}",
"System.Core, PublicKeyToken={0}",
"System.Data, PublicKeyToken={0}",
"System.Design, PublicKeyToken={1}",
"System.DirectoryServices, PublicKeyToken={1}",
"System.Drawing, PublicKeyToken={1}",
"System.Drawing.Design, PublicKeyToken={1}",
"System.Management, PublicKeyToken={1}",
"System.Messaging, PublicKeyToken={1}",
"System.Runtime.Remoting, PublicKeyToken={0}",
"System.Security, PublicKeyToken={1}",
"System.ServiceProcess, PublicKeyToken={1}",
"System.Web, PublicKeyToken={1}",
"System.Web.RegularExpressions, PublicKeyToken={1}",
"System.Web.Services, PublicKeyToken={1}",
"System.Windows.Forms, PublicKeyToken={0}",
"System.Xml, PublicKeyToken={0}",
}; String EcmaPublicKeyToken = "b77a5c561934e089";
String MSPublicKeyToken = "b03f5f7f11d50a3a"; // Get the version of the assembly containing System.Object
// We'll assume the same version for all the other assemblies
Version version = typeof(System.Object).Assembly.GetName().Version; // Explicitly load the assemblies that we want to reflect over
foreach (String a in assemblies)
{
String AssemblyIdentity =
String.Format(a, EcmaPublicKeyToken, MSPublicKeyToken) +
", Culture=neutral, Version=" + version;
Assembly.Load(AssemblyIdentity);//在AppDomain中加载程序集
}
}
- 找到所有的派生自MemberInfo的类型
public static void Demo2()
{
Assembly[] oldAssembly = AppDomain.CurrentDomain.GetAssemblies();//未加载程序集时的app Domain中的程序集 LoadAssemblies();//加载程序集
var newAssemblyName = (from a in AppDomain.CurrentDomain.GetAssemblies()//获取在原程序集中的程序集
where Array.IndexOf(oldAssembly, a) >= 0
orderby a.FullName
select a.FullName).ToArray(); Array.ForEach<string>(newAssemblyName, x => Display(3, x));//打印原程序集
Console.WriteLine("Compare Assemblys end"); var allTypes =
(from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.ExportedTypes
where typeof(MemberInfo).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())//获取所有派生自Exception的类型.
orderby t.Name
select t).ToArray();
Display(0, WalkInheritanceHierachy(new StringBuilder(), 0, typeof(MemberInfo), allTypes).ToString());//迭代打印这些类型.
}
- 迭代查找派生关系
private static StringBuilder WalkInheritanceHierachy(StringBuilder sb,int indent,Type baseType,IEnumerable<Type> allTypes)//迭代打印函数
{
string spaces = new string(' ', indent * 3);//前缀空格
sb.AppendLine(spaces + baseType.FullName);//添加基类的全名,新一行.
foreach(var t in allTypes)
{
if (t.GetTypeInfo().BaseType != baseType) continue;//如果这个类不是另一个类的基列,继续.
WalkInheritanceHierachy(sb, indent + 1, t, allTypes);//如果找到某个类是派生类,则将这个类作为基类,去查找新的派生类.
}
return sb;
}
- 结果:
System.Reflection.MemberInfo
System.Reflection.EventInfo
System.Runtime.InteropServices.ComAwareEventInfo
System.Reflection.FieldInfo
System.Reflection.Emit.FieldBuilder
System.Reflection.MethodBase
System.Reflection.ConstructorInfo
System.Reflection.Emit.ConstructorBuilder
System.Reflection.MethodInfo
System.Reflection.Emit.DynamicMethod
System.Reflection.Emit.MethodBuilder
System.Reflection.PropertyInfo
System.Reflection.Emit.PropertyBuilder
System.Type
System.Reflection.TypeInfo
System.Reflection.Emit.EnumBuilder
System.Reflection.Emit.GenericTypeParameterBuilder
System.Reflection.Emit.TypeBuilder
System.Reflection.TypeDelegator
4,BindingFlags
字段
CreateInstance | 512 |
创建类的实列,Invoke类的实列调用类的构造器时使用. |
DeclaredOnly | 2 |
指定当前类上面声明的成员 |
Default | 0 |
指定未定义任何绑定标志。 |
DoNotWrapExceptions | 33554432 | |
ExactBinding | 65536 |
未知... |
FlattenHierarchy | 64 |
指定应返回层次结构往上的公共成员和受保护静态成员。. 静态成员包括字段、方法、事件和属性。. 不支持嵌套类型。 |
GetField | 1024 |
指定应返回指定字段的值。此标志会传递给 |
GetProperty | 4096 |
指定应返回指定属性的值。此标志会传递给 |
IgnoreCase | 1 |
指定在绑定时不应考虑成员名称的大小写。 |
IgnoreReturn | 16777216 |
在 COM |
Instance | 4 |
指定实例成员要包括在搜索中。 |
InvokeMethod | 256 |
指定要调用的方法。非构造器 此标志会传递给 |
NonPublic | 32 |
指定非公共成员要包括在搜索中。 |
OptionalParamBinding | 262144 |
返回其参数计数与提供的参数数量匹配的成员集。 此绑定标志用于参数具有默认值的方法和使用变量参数 (varargs) |
Public | 16 |
指定公共成员要包括在搜索中。 |
PutDispProperty | 16384 |
指定应调用 COM 对象上的 |
PutRefDispProperty | 32768 |
指定应调用 COM 对象上的 |
SetField | 2048 |
指定应设置指定字段的值。 |
SetProperty | 8192 |
指定应设置指定属性的值。 |
Static | 8 |
指定静态成员要包括在搜索中。 |
SuppressChangeType | 131072 |
未实现。 |
public class BindingFlagsRef
{
public static void Go()
{
// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof(TestClass); Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public |//调用类的静态方法.注意Binder=null,Target=null
BindingFlags.Static, null, null, new object[] { }); // BindingFlags.InvokeMethod
// Call an instance method.
TestClass c = new TestClass();
Console.WriteLine();
Console.WriteLine("Invoking an instance method.");
Console.WriteLine("----------------------------");
c.GetType().InvokeMember("AddUp", BindingFlags.InvokeMethod, null, c, new object[] { });//调用实列的方法,注意,Target=c;
c.GetType().InvokeMember("AddUp", BindingFlags.InvokeMethod, null, c, new object[] { });//调用实列的方法,注意,Target=c; // BindingFlags.InvokeMethod
// Call a method with parameters.
object[] args = new object[] { 100.09, 184.45 };
object result;
Console.WriteLine();
Console.WriteLine("Invoking a method with parameters.");
Console.WriteLine("---------------------------------");
result = t.InvokeMember("ComputeSum", BindingFlags.InvokeMethod , null, null, args);//调用带参数的方法.
Console.WriteLine("{0} + {1} = {2}", args[0], args[1], result); // BindingFlags.GetField, SetField
Console.WriteLine();
Console.WriteLine("Invoking a field (getting and setting.)");
Console.WriteLine("--------------------------------------");
// Get a field value.
result = t.InvokeMember("Name", BindingFlags.GetField, null, c, new object[] { });//获取和设定字段.
Console.WriteLine("Name == {0}", result);
// Set a field.
t.InvokeMember("Name", BindingFlags.SetField, null, c, new object[] { "NewName" });
result = t.InvokeMember("Name", BindingFlags.GetField, null, c, new object[] { });
Console.WriteLine("Name == {0}", result); Console.WriteLine();
Console.WriteLine("Invoking an indexed property (getting and setting.)");
Console.WriteLine("--------------------------------------------------");
// BindingFlags.GetProperty
// Get an indexed property value.
int index = 3;
result = t.InvokeMember("Item", BindingFlags.GetProperty, null, c, new object[] { index });//获取索引器的值.
Console.WriteLine("Item[{0}] == {1}", index, result);
// BindingFlags.SetProperty
// Set an indexed property value.
index = 3;
t.InvokeMember("Item", BindingFlags.SetProperty, null, c, new object[] { index, "NewValue" });//设定索引器的值.
result = t.InvokeMember("Item", BindingFlags.GetProperty, null, c, new object[] { index });
Console.WriteLine("Item[{0}] == {1}", index, result); Console.WriteLine();
Console.WriteLine("Getting a field or property.");
Console.WriteLine("----------------------------");
// BindingFlags.GetField
// Get a field or property.
result = t.InvokeMember("Name", BindingFlags.GetField | BindingFlags.GetProperty, null, c,
new object[] { });
Console.WriteLine("Name == {0}", result);//获取属性或者字段的对象.
// BindingFlags.GetProperty
result = t.InvokeMember("Value", BindingFlags.GetField | BindingFlags.GetProperty, null, c,
new object[] { });//获取属性或者字段的对象.
Console.WriteLine("Value == {0}", result); Console.WriteLine();
Console.WriteLine("Invoking a method with named parameters.");
Console.WriteLine("---------------------------------------");
// BindingFlags.InvokeMethod
// Call a method using named parameters.
object[] argValues = new object[] { "Mouse", "Micky" };
String[] argNames = new String[] { "lastName", "firstName" };
t.InvokeMember("PrintName", BindingFlags.InvokeMethod, null, null, argValues, null, null,//指定Named类型的方法.
argNames); Console.WriteLine();
Console.WriteLine("Invoking a default member of a type.");
Console.WriteLine("------------------------------------");
// BindingFlags.Default
// Call the default member of a type.
Type t3 = typeof(TestClass2);
t3.InvokeMember("", BindingFlags.InvokeMethod | BindingFlags.Default, null, new TestClass2(),
new object[] { });//利用特性MemberDefault,和反射配合指定使用方法.当前是Print. // BindingFlags.Static, NonPublic, and Public
// Invoking a member with ref parameters.
Console.WriteLine();
Console.WriteLine("Invoking a method with ref parameters.");
Console.WriteLine("--------------------------------------");
MethodInfo m = t.GetMethod("Swap");
args = new object[2];
args[0] = 1;
args[1] = 2;
//m.Invoke(new TestClass(), args);//和调用有参的形式一样,这是新的办法
t.InvokeMember("Swap", BindingFlags.InvokeMethod, null, new TestClass(), args);//这是通过type来调用.
Console.WriteLine("{0}, {1}", args[0], args[1]); // BindingFlags.CreateInstance
// Creating an instance with a parameterless constructor.
Console.WriteLine();
Console.WriteLine("Creating an instance with a parameterless constructor.");
Console.WriteLine("------------------------------------------------------");
object cobj = t.InvokeMember("TestClass", BindingFlags.Public |//注意3个BindingFlags的应用.
BindingFlags.Instance | BindingFlags.CreateInstance,
null, null, new object[] { });//创建类的实列的另外一个办法.
Console.WriteLine("Instance of {0} created.", cobj.GetType().Name); // Creating an instance with a constructor that has parameters.
Console.WriteLine();
Console.WriteLine("Creating an instance with a constructor that has parameters.");
Console.WriteLine("------------------------------------------------------------");
cobj = t.InvokeMember("TestClass", BindingFlags.Public |//创建有参的构造器,并且返回实列.
BindingFlags.Instance | BindingFlags.CreateInstance,
null, null, new object[] { "Hello, World!" });
Console.WriteLine("Instance of {0} created with initial value '{1}'.", cobj.GetType().Name,
cobj.GetType().InvokeMember("Name", BindingFlags.GetField, null, cobj, null)); // BindingFlags.DeclaredOnly
Console.WriteLine();
Console.WriteLine("DeclaredOnly instance members.");
Console.WriteLine("------------------------------");
System.Reflection.MemberInfo[] memInfo =
t.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance |//考虑在本类中创建(非继承,实列,公共)的成员集合.
BindingFlags.Public);
for (int i = 0; i < memInfo.Length; i++)
{
Console.WriteLine(memInfo[i].Name);
} // BindingFlags.IgnoreCase
Console.WriteLine();
Console.WriteLine("Using IgnoreCase and invoking the PrintName method.");
Console.WriteLine("---------------------------------------------------");
t.InvokeMember("printname", BindingFlags.IgnoreCase | BindingFlags.Static |//忽略大小写
BindingFlags.Public | BindingFlags.InvokeMethod, null, null, new object[]
{"Brad","Smith"}); // BindingFlags.FlattenHierarchy
Console.WriteLine();
Console.WriteLine("Using FlattenHierarchy to get inherited static protected and public members.");
Console.WriteLine("----------------------------------------------------------------------------");
FieldInfo[] finfos = typeof(MostDerived).GetFields(BindingFlags.NonPublic | BindingFlags.Public |//NoPublic是Protected对象.
BindingFlags.Static | BindingFlags.FlattenHierarchy);//返回受保护静态成员.
foreach (FieldInfo finfo in finfos)
{
Console.WriteLine("{0} defined in {1}.", finfo.Name, finfo.DeclaringType.Name);//DeclaringType...成员所定义的Type
} Console.WriteLine();
Console.WriteLine("Without FlattenHierarchy.");
Console.WriteLine("-------------------------");
finfos = typeof(MostDerived).GetFields(BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static);
foreach (FieldInfo finfo in finfos)
{
Console.WriteLine("{0} defined in {1}.", finfo.Name, finfo.DeclaringType.Name);
}
} }
public class TestClass
{
public String Name;
private Object[] values = new Object[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; public Object this[int index]
{
get
{
return values[index];
}
set
{
values[index] = value;
}
} public Object Value
{
get
{
return "the value";
}
} public TestClass() : this("initialName") { }
public TestClass(string initName)
{
Name = initName;
} int methodCalled = 0; public static void SayHello()
{
Console.WriteLine("Hello");
} public void AddUp()
{
methodCalled++;
Console.WriteLine("AddUp Called {0} times", methodCalled);
} public static double ComputeSum(double d1, double d2)
{
return d1 + d2;
} public static void PrintName(String firstName, String lastName)
{
Console.WriteLine("{0},{1}", lastName, firstName);
} public void PrintTime()
{
Console.WriteLine(DateTime.Now);
} public void Swap(ref int a, ref int b)
{
int x = a;
a = b;
b = x;
} }
[DefaultMemberAttribute("PrintTime")]
public class TestClass2
{
public void PrintTime()
{
Console.WriteLine(DateTime.Now);
}
} public class Base
{
static int BaseOnlyPrivate = 0;
protected static int BaseOnly = 0;
}
public class Derived : Base
{
public static int DerivedOnly = 0;
}
public class MostDerived : Derived { }
上面的列子枚举了差不多的一些反射调用一个类中的方法或者字段或者其他的一些用法
5,Binder-----从候选者列表中选择一个成员,并执行实参类型到形参类型的类型转换,需要实现派生
Binder用来自定义选择匹配的方法,字段等...一般不用,或者使用Type.DefaultBinder使用.
6,构造类的实列
通过反射构造类的实列常用方法:
public static void CallCreateObjectByReflection()
{
//方法1,使用createInstance--type方法.
Type t = typeof(TestClass);
TestClass t1 = (TestClass)Activator.CreateInstance(t, new object[] { });
Display(0, t1.Name);
//方法2,使用程序集的方法,第一个参数可以是null,当前程序集,或者是Assembly.GetEnterAssembly.ToString(),返回程序集的全名.
var t2 = (TestClass)Activator.CreateInstance(null, typeof(TestClass).FullName).Unwrap();
Display(0, Assembly.GetEntryAssembly().ToString());
Display(0, t2.Name);
//方法3,使用CreateInstanceFrom生成.
var path = Assembly.GetEntryAssembly().CodeBase;
var t3 = (TestClass)Activator.CreateComInstanceFrom(path, typeof(TestClass).FullName).Unwrap();
Display(0, "path is {0},type is {1}", path, t3);
//方法4,使用AppDomain的CreateInstance;注意,如果是另外的appDomain则需要类型是MarshalRefObject的派生类,或者可序列化对象.
AppDomain ad0 = AppDomain.CreateDomain("Ad0");
var t4=AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(path, typeof(TestClass).FullName);
Display(0, "path is {0},type is {1}", path, t4);
//方法5,使用InVokeMember调用构造器.
var t5 = (TestClass)t.InvokeMember("", BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
Display(0, t5.Name);
//方法6,使用ConstructorInfo,其实类似上面的
ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) });
var t6=(TestClass)ci.Invoke(new object[] { "new Constructor" });
Display(0, t6.Name);
//方法7,数组类型创建实列
Array t7 = Array.CreateInstance(t, 10);
for(int i=0;i<t7.Length;i++)
{
t7.SetValue(new TestClass(i.ToString()), i);
}
int count=0;
Array.ForEach<TestClass>((TestClass[])t7, x => Display(count++, x.Name));
//方法7_1,另外一个方法创建数组的实列.
Type t71 = t.MakeArrayType();
var t72 =(TestClass[]) Activator.CreateInstance(t71, new object[] { 10 });
Display(0, t72.Length.ToString()); //方法8,委托类型创建实列
MethodInfo mi = t.GetMethod("AddUp");
var t8 = new TestClass();
Delegate d = Delegate.CreateDelegate(typeof(Action), t8, mi);
d.DynamicInvoke();
d.DynamicInvoke(); //方法9,构造泛型实列
Type openType = typeof(Dictionary<,>);//首先创建openType
Type closeType = openType.MakeGenericType(typeof(string),typeof(string));//创建封闭Type
Type ListOpenType = typeof(List<>);//创建新的OpenType
Type ListCloseType = ListOpenType.MakeGenericType(closeType);//创建复合的封闭对象
object o = Activator.CreateInstance(ListCloseType);//创建类型对象的实列.
Display(0, o.ToString()); } }
7,设计支持加载项的程序.
在使用过程中发现System.IO.FileLoadException错误,的原因为:
- 如果某个类是强名称,那么所有它引用的类也必须都是强名称.
我因为忘记给HostSDK进行强名称设定,所以出错.HostSDK进行之后,AddIn也要进行.
1,设计接口类:
//HostSDK.cs
using System; namespace Winteliect.HostSDK
{
public interface IAddin
{
string DoSomeThing(Int32 x); } }
2,设计接口实现类
//AddInTypes.cs
using System;
using Winteliect.HostSDK; namespace AddInTypes
{
public sealed class AddIn_A:IAddin
{
public AddIn_A(){}
public string DoSomeThing(Int32 x)
{
return "AddIn_A:"+x.ToString();
}
}
public sealed class AddIn_B:IAddin
{
public AddIn_B(){}
public string DoSomeThing(Int32 x)
{
return "AddIn_B:"+(2*x).ToString();
}
}
}
3,进行编译dll
- sn -k host.snk
- csc.exe /out:HostSDK.dll /t:library /keyfile:host.snk HostSDK.cs---生成HostSDK.dll
- csc.exe /out:AddInTypes.dll /t:library /r:HostSDK.dll /keyfile:host.snk AddInTypes.cs---生成AddInTypes.dll
4,在程序中使用
public static void DynamicLoadDemo()
{ string path = Assembly.GetExecutingAssembly().Location;//获取.exe的详细路径
string AddInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);//获取.exe的目录.../Debug
var dlls = Directory.EnumerateFiles(AddInDir, "*.dll");//
var types =
(from file in dlls
let asb = Assembly.LoadFrom(file)
from t in asb.ExportedTypes
where t.IsPublic && t.IsClass && (typeof(IAddin).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()))
select t).ToList();//获取有该接口的类. types.ForEach(//创建类的实列并且工作.
x =>
{
IAddin t = (IAddin)Activator.CreateInstance(x);
Display(0,t.DoSomeThing(10)); });
}
clr via c# 程序集加载和反射集(一)的更多相关文章
- clr via c# 程序集加载和反射(2)
查看,clr via c# 程序集加载和反射(1) 8,发现类型的成员: 字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性 ...
- CLR中的程序集加载
CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...
- 重温CLR(十七)程序集加载和反射
本章主要讨论在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息.创建类型的实例以及访问类型的成员.可利用本章讲述的内容创建动态可扩展应用程序. 反射使用的典型场景一般是由一家公司创建宿主应 ...
- 【C#进阶系列】23 程序集加载和反射
程序集加载 程序集加载,CLR使用System.Reflection.Assembly.Load静态方法,当然这个方法我们自己也可以显式调用. 还有一个Assembly.LoadFrom方法加载指定路 ...
- 【C#】解析C#程序集的加载和反射
目录结构: contents structure [+] 程序集 程序集的加载 发现程序集中的类型 反射对类型成员的常规操作 发现类型的成员 创建类型的实例 绑定句柄减少进程的内存消耗 解析自定义特性 ...
- .NET 的程序集加载上下文
原文:.NET 的程序集加载上下文 我们编写的 .NET 应用程序会使用到各种各样的依赖库.我们都知道 CLR 会在一些路径下帮助我们程序找到依赖,但如果我们需要手动控制程序集加载路径的话,需要了解程 ...
- arcgis python 使用光标和内存中的要素类将数据加载到要素集 学习:http://zhihu.esrichina.com.cn/article/634
学习:http://zhihu.esrichina.com.cn/article/634使用光标和内存中的要素类将数据加载到要素集 import arcpy arcpy.env.overwriteOu ...
- Clr Via C#读书笔记---程序集的加载和反射
#1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...
- .net 程序集的加载与反射
一. 程序集的加载: 在CLR内部使用System.Reflection.Assembly类的静态LoadFrom方法尝试加载程序集. LoadFrom方法在内部调用Assembly的Load方法,将 ...
随机推荐
- KD-tree 学习小记
考 \(NOI\) 时不会,感觉很亏.于是学了一上午,写了一晚上. 感觉这东西就是个复杂度玄学的高级暴力 (大雾 KD-tree 基本信息 \(D\) 就是 \(Dimension\) ,维度的意思. ...
- [bzoj4827] [洛谷P3723] [Hnoi2017] 礼物
Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是 ...
- nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.报错解决
近期在学springboot,学的时候遇到这个错,网上查了好多,改了不行,后来发现自己的配置类没有加@SpringBootApplication注解 Exception encountered dur ...
- python条件与循环-循环
1 while语句 while用于实现循环语句,通过判断条件是否为真,来决定是否继续执行. 1.1 一般语法 语法如下: while expression: suite_to_repeat 1.2 计 ...
- Ubuntu下配置GitHub
使用GitHub进行代码托管是如此地方便,原来一直在Windows下进行操作,非常的简单,由于其图形化界面将所有这些都隐藏起来了. 还是不得不吐槽一下自己,非得将自己的系统装为Ubuntu... 言归 ...
- linux--->lnmp环境调试环境配置
lnmp环境调试环境配置 nginx是一个web服务器,因此nginx的access日志只有对访问页面的记录,不会有php 的 error log信息. nginx把对php的请求发给php-fpm ...
- linux--->PHP常用模块解析
PHP常用模块解析 php-gd :GD库是php处理图形的扩展库,GD库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片,也可以给图片加水印 php-ldap :LDAP是轻量 ...
- Android教程2020 - RecyclerView显示多种item
Android教程2020 - 系列总览 本文链接 前面我们已经用RecyclerView显示一些数据.也知道如何获取滑动的距离. 前面我们的列表中显示的都是同类数据.如果要在一个列表中显示不同类别的 ...
- PyTables的下载和安装
先说下我的环境:Ubuntu 16.04.5 LTS1.下载:git clone https://github.com/PyTables/PyTables.git 如果提示没有git 命令,需要先安装 ...
- hive安装启动错误总结
错误一: Exception in thread "main" java.lang.NoClassDefFoundError: jline/console/completer/Ar ...