Tom*_*lis 18 .net c# reflection
所以我试着搜索,希望有人对此有一个很好的解释,没有运气.
我问了我的另一个朋友一个不同的问题(我现在已经忘记了),他的回答只是在他签字之前的"反思".
我仍然是C#世界的新手,曾经是业余的VB.net程序员(也是JavaScript,ActionScript和C),我正在尽我所能去掌握这些先进的概念.
有许多哲学答案 - "应用程序在看自己" - 但它们没有提供任何实际的提示,说明实际发生的事情或在该环境中如何使用它.
那么,什么是反思,为什么重要,以及为什么/如何使用它?
Hej*_*man 14
Reflection提供了在运行时确定事物和执行代码的能力.
你不具备使用它,如果你不想,但它是动态行为非常方便.
例如:
a)您可以使用反射来配置应用程序,方法是加载外部配置文件并根据它启动服务.您的应用程序不必事先知道实现这些服务的类,只要它们符合特定的接口或API即可.
b)使用反射,您可以动态生成类和代码,这简化了某些编程任务,因为程序员不必显式创建所有需要的代码.
c)对于通过检查代码工作的程序来说,反思也是非常宝贵的.一个例子是IDE或UI设计师.
d)反射可以帮助您减少样板代码.
e)反射在您的代码中定义迷你域特定语言(DSL)很方便.
(我的定义)反射是能够编写在运行时执行代码的静态代码,通常在编译时确定.
例如,我可以通过编译该命令来调用类方法来绘制,例如:
pen.DrawLine()
Run Code Online (Sandbox Code Playgroud)
或者通过反射,我可以先看看我的对象是否有一个名为"drawline"的方法,如果有,请调用它.(注意这不是实际的C#Reflection语法)
if(pen.Methods.Contains("DrawLine"))
{
pen.InvokeMethod("DrawLine"))
}
Run Code Online (Sandbox Code Playgroud)
我不是反射大师,但我使用反射作为插件架构.
通过反射,我可以在运行时加载.NET程序集(在本例中为dll),找出.NET程序集中的所有类型,查看是否有任何类型实现特定的接口,如果是,则实例化class,我调用接口方法.
我知道用例有点技术性,但本质上反射允许我动态加载插件(即在运行时),并允许我对它进行类型安全的调用.
反射最常见的用途是以前称为RTTI(运行时类型信息)的扩展,主要是C++程序员的领域.
反射是.net构建方式的副作用,Microsoft选择将其用于创建Visual Studio的库和.net运行时公开给Microsoft以外的开发人员.
大多数反射库都侧重于可以在运行时调用的类型发现和创建.这允许一些非常强大的自引用代码.以下示例位于我们的配置管理系统的核心(为清晰起见,删除了一些位):
public static IMyCompanySetting UnwrapSetting(XmlNode settingNode)
{
string typeName = settingNode.Attributes["type"].Value;
string typeAssembly;
if(settingNode.Attributes["assembly"] != null)
{
typeAssembly = settingNode.Attributes["assembly"].Value;
}
Type settingType = null;
Assembly settingAssembly = null;
try
{
// Create an object based on the type and assembly properties stored in the XML
try
{
settingAssembly = Assembly.Load(typeAssembly);
if (settingAssembly == null)
{
return null;
}
}
catch (Exception outerEx)
{
try
{
settingType = GetOrphanType(typeName);
}
catch (Exception innerEx)
{
throw new Exception("Failed to create object " + typeName + " :: " + innerEx.ToString(), outerEx);
}
}
// We will try in order:
// 1. Get the type from the named assembly.
// 2. Get the type using its fully-qualified name.
// 3. Do a deep search for the most basic name of the class.
if (settingType == null && settingAssembly != null) settingType = settingAssembly.GetType(typeName);
if (settingType == null) settingType = Type.GetType(typeName);
if (settingType == null) settingType = GetOrphanType(typeName);
if (settingType == null) throw new System.Exception(
String.Format("Unable to load definition for type {0} using loosest possible binding.", typeName));
}
catch (Exception ex)
{
throw new CometConfigurationException(
String.Format("Could not create object of type {0} from assembly {1}", typeName, typeAssembly), ex);
}
bool settingIsCreated = false;
IMyCompanySetting theSetting = null;
// If the class has a constructor that accepts a single parameter that is an XML node,
// call that constructor.
foreach (ConstructorInfo ctor in settingType.GetConstructors())
{
ParameterInfo[] parameters = ctor.GetParameters();
if (parameters.Length == 1)
{
if (parameters[0].ParameterType == typeof(XmlNode))
{
object[] theParams = { settingNode };
try
{
theSetting = (IMyCompanySetting)ctor.Invoke(theParams);
settingIsCreated = true;
}
catch (System.Exception ex)
{
// If there is a pre-existing constructor that accepts an XML node
// with a different schema from the one provided here, it will fail
// and we'll go to the default constructor.
UtilitiesAndConstants.ReportExceptionToCommonLog(ex);
settingIsCreated = false;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码允许我们创建无限数量的类来实现IMyCompanySetting,并使用XML对它们进行序列化和反序列化.然后,给定一块XML作为对象序列化的输出,系统可以将其转换回对象,即使对象本身来自序列化库没有静态链接的库.
如果没有它,有三件事反映在这里是不可能的:
在运行时根据其名称加载程序集.
在运行时根据其名称从程序集加载对象.
根据编译时未知的类对象的签名调用对象构造函数.
假设您有一个接口的两个替代实现。您希望允许用户通过简单的文本配置文件选择其中之一。
通过反射,您可以简单地从配置文件中读取要使用其实现的类的名称(作为字符串),并实例化该类的实例。
| 归档时间: |
|
| 查看次数: |
7619 次 |
| 最近记录: |