当前位置:  开发笔记 > 编程语言 > 正文

C#:有人可以解释反思的实用性吗?

如何解决《C#:有人可以解释反思的实用性吗?》经验,为你挑选了3个好方法。

所以我试着搜索,希望有人对此有一个很好的解释,没有运气.

我问了我的另一个朋友一个不同的问题(我现在已经忘记了),他的回答只是在他签字之前的"反思".

我仍然是C#世界的新手,曾经是业余的VB.net程序员(也是JavaScript,ActionScript和C),我正在尽我所能去掌握这些先进的概念.

有许多哲学答案 - "应用程序在看自己" - 但它们没有提供任何实际的提示,说明实际发生的事情或在该环境中如何使用它.

那么,什么是反思,为什么重要,以及为什么/如何使用它?



1> Hejazzman..:

Reflection提供了在运行时确定事物和执行代码的能力.

你不具备使用它,如果你不想,但它是动态行为非常方便.

例如:

a)您可以使用反射来配置应用程序,方法是加载外部配置文件并根据它启动服务.您的应用程序不必事先知道实现这些服务的类,只要它们符合特定的接口或API即可.

b)使用反射,您可以动态生成类和代码,这简化了某些编程任务,因为程序员不必显式创建所有需要的代码.

c)对于通过检查代码工作的程序来说,反思也是非常宝贵的.一个例子是IDE或UI设计师.

d)反射可以帮助您减少样板代码.

e)反射在您的代码中定义迷你域特定语言(DSL)很方便.



2> Alan..:

(我的定义)反射是能够编写在运行时执行代码的静态代码,通常在编译时确定.

例如,我可以通过编译该命令来调用类方法来绘制,例如:

pen.DrawLine()

或者通过反射,我可以先看看我的对象是否有一个名为"drawline"的方法,如果有,请调用它.(注意这不是实际的C#Reflection语法)

 if(pen.Methods.Contains("DrawLine"))
 {
    pen.InvokeMethod("DrawLine"))
 }

我不是反射大师,但我使用反射作为插件架构.

通过反射,我可以在运行时加载.NET程序集(在本例中为dll),找出.NET程序集中的所有类型,查看是否有任何类型实现特定的接口,如果是,则实例化class,我调用接口方法.

我知道用例有点技术性,但本质上反射允许我动态加载插件(即在运行时),并允许我对它进行类型安全的调用.



3> Yes - that J..:

反射最常见的用途是以前称为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;
                    }
                }
            }
        }

这段代码允许我们创建无限数量的类来实现IMyCompanySetting,并使用XML对它们进行序列化和反序列化.然后,给定一块XML作为对象序列化的输出,系统可以将其转换回对象,即使对象本身来自序列化库没有静态链接的库.

如果没有它,有三件事反映在这里是不可能的:

在运行时根据其名称加载程序集.

在运行时根据其名称从程序集加载对象.

根据编译时未知的类对象的签名调用对象构造函数.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有