建议的设计模式或反射的基本用例?

时间:2016-06-24 15:34:11

标签: c# design-patterns system.reflection

我知道一些r​​election功能,但我永远不会理解我何时以及为什么要使用它们,我想了解一些关于如何以及何时使用它的好主意的例子? 你知道用反射进行的设计模式有哪些? 是否只有使用反射才能完成任何操作?

2 个答案:

答案 0 :(得分:1)

非常常见的用例:在运行时调用函数。

想象一下接受像这样的请求的服务器

txtEditText = (EditText) findViewById(R.id.txtEditText);
txtEditText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);

您需要编写查找以查找所请求方法的代码并进行调用。你可以用一个很大的switch语句做到这一点,但在某些情况下它不起作用(也许你允许在具有不同功能的不同时间加载dll),你也需要弄清楚需要对参数进行哪些转换。 / p>

相反,你做

foo(3)
bar("joe")
wiz(42.0)

答案 1 :(得分:0)

Reflection是实现 difuse 编程的强大工具。当你知道自己想要什么,但是你不知道在运行之前你会得到什么,反思就是答案。

常见情景:

1)元编程:属性。

当您需要扩展语言以在访问修饰符(publicprivate ...)不足的情况下提供更多含义时,您可以使用属性

属性与程序集成员和类型成员相关联,需要使用反射。

给定以下属性和使用整个属性的类:

public class NameAttribute : Attribute
{
    public NameAttribute(string name) 
    {
         Name = name;
    }

    public string Name { get; }
}

[Name("Custom name")]
public class A
{

}

...你使用反射获得属性:

NameAttribute nameAttr = typeof(A).GetCustomAttribute<NameAttribute>();

由于属性是常规类,因此它们提供了一种强大的方法,可以在编译时将元数据与程序集,类,接口,枚举和类型成员相关联,以便在运行时根据一组条件获取它们。

2)实施约定优于配置

约定优于配置是一个强大的开发范例,用于实现几乎零配置的框架和库,如果遵循一些规则,它们会自动配置。

反思在这里发挥着重要作用。例如,当使用反射使用Code First策略时,Entity Framework可以确定数据库中的主键

鉴于以下实体:

public class Customer
{
     public Guid Id { get; set }
     public string Name { get; set; }
}

...实体框架可能会按惯例知道Id将是主键,并且使用反射可以查明是否存在Id属性:

PropertyInfo idProperty = typeof(Customer).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance);

if(idProperty != null) 
{
    // Yes, it has an Id property!
}

3)在运行期间做出决定

由于反射使您的代码能够内省并执行您在编译期间可以执行的几乎所有操作(显然,具有高性能影响),因此它允许您获取基于搜索的方法,属性或其他任何内容,并调用它们以获取或设定值。

4)表达树:内省表达的身体

表达式树是C#中一个强大的工具,可以将代码生成为数据结构

例如,我可以定义一个类FileChecker并在表达式树中包含对其Exists方法的调用,然后调用哪个方法,它的参数甚至声明了运行期间使用反射的整个方法:

public class FileChecker
{
     public bool Exists(string filePath) { }
}

Checker checker = new Checker();
Expression<Func<bool>> expr = () => checker.Exists(@"C:\hello.txt");

MethodCallExpression methodCallExpr = (MethodCallExpression)expr.Body;

MethodInfo calledMethod = methodCallExpr.Method;
IEnumerable<ParameterInfo> inputParams = calledMethod.GetParameters();
Type declaringType = calledMethod.DeclaringType;